Customer Data Cost Simulator
Open the simulator in a browser. Choose In Motion, At Rest, or Combined, then set the number of organizations and their workload. The standalone calculator works offline and exports the assumptions, capacity estimates, and node placement as CSV.
| Workload | Evidence stored | What drives capacity |
|---|---|---|
| In Motion | Non-other activity events such as uploads, downloads, sharing, and AI use | Event arrival rate, non-other share, retained months, recent activity, and the history backfill window |
| At Rest | Non-other file records with classification, location, access, and lifecycle information | Files per TB, classifiable share, non-other share, scan and refresh windows, and retained snapshots |
| Combined | Both evidence sets | Sum of the two independently sized workloads, with a shared entity directory |
Entities are distinct directory entries such as contacts, employees, external organizations, and AI agents. The entity count sizes the directory and per-scope counter lookups, and sets an upper bound on distinct actor counters in the In Motion workload. The simulator keeps entities separate from event and file totals.
The Non-other evidence saved (%) assumption defaults to 40%. It applies to all incoming In Motion events and to classifiable At Rest files. The simulator uses the saved records to size MongoDB storage, indexes, cache, and writes, including counter updates and rebuilds. It bases source scan volume on every discovered file and directory overhead on the entity count.
In Motion
2 million events/month × 36 months = 72 million incoming events, of which 28.8 million are saved per organization at 40%. An activity that refers to a file contributes one event to this stream. The event volume is the organization's total across up to five source scopes. The number of scopes affects how many distinct counter groups the model estimates.
- Retained events = events per month × months retained × non-other share. The peak database write estimate is the average arrival rate × non-other share × peak multiplier. A history backfill spreads writes for the retained event count over its target window. These two rates size event writes and counter updates.
- Active working set depends on the recent months accessed and the fraction of data and index pages read. Extending cold retention adds stored rows and index entries, while the recent series can stay the same size.
- Counter groups estimate the live monthly activity, risk, classification, AI, and relationship queries. The historical daily comparison measures the difference from daily trend and daily detail buckets for events. File inventory stays outside that comparison.
At Rest
At Rest measures a current inventory of files. A completed scan refreshes the inventory. Optional full historical snapshots add copies of that inventory. Use a single retained snapshot for a current-state deployment.
| One inventory snapshot | Files discovered | Classifiable files | Non-other files saved at 40% |
|---|---|---|---|
| 1 TB scanned × 1.3M files/TB, one-third of files classifiable | 1,300,000 | ≈433,333 | ≈173,333 |
| 3 TB scanned × 1.3M files/TB, one-third of files classifiable | 3,900,000 | 1,300,000 | 520,000 |
| 3 TB scanned × 1.3M files/TB, 1.3 TB classifiable at equal density | 3,900,000 | 1,690,000 | 676,000 |
File-count eligibility and source-byte eligibility use different denominators. Under equal file density, one-third of files at 3 TB represents roughly 1 TB. Choosing 1.3 TB explicitly classifiable uses a 43.3% byte share and assumes eligible files have the same average size as all discovered files.
- Stored file records = classifiable files per snapshot × non-other share × snapshots retained. Each snapshot contributes counters from its saved files.
- Scan and writes. A source scan covers all discovered files. The first load or full snapshot capture writes the non-other records for one inventory. A routine refresh uses the changed-file percentage (5% by default) to size writes against the saved file count. Counter refreshes budget for removing old classifications and applying new ones. Optional history adds retained storage and a larger counter rebuild, which reads the retained inventory through its own window (168 hours by default).
- File counters size inventory summaries, classification, storage by location and label, access and exposure, and lifecycle policy. They use file and byte measures and the snapshot identity. A file with several permissions can be counted under its broadest effective audience for a distinct-file total. Snapshot retention and the amount of inventory accessed set the file working set independently of event retention.
- Inventory scopes allow up to six source partitions including On-Premises Shared Folders. These scope inputs affect counters, while scanned TB defines the total source inventory for the organization.
The supplied Microsoft 365 At Rest prototype shows 9,986,404 items over about 268 TB, or about 37,300 items/TB. The entered planning density of 1.3M files/TB instead implies 348.4M discovered files at 268 TB. The AI Artifacts At Rest prototype uses current inventory, distinct artifacts, classification coverage, and verified access. Use measured file density, eligibility, and refresh rates from the customer's inventory when available.
Combined and node placement
Combined first sizes event history and file inventory independently. Counter cardinality, evidence indexes, and hot cache are computed for each stream. The planner then uses their resource totals and a shared directory, with lookup entries budgeted per source scope. Each provisioned node gets its own disk reserve. The fleet estimate assumes the selected sizing workloads can run concurrently.
The planner compares putting whole evidence and counter databases together, placing them separately, and placing balanced partitions when they help fit. RAM, provisioned disk, CPU, and disk I/O each constrain placement. The highest resource demand divided by its per-node budget gives a lower bound on nodes. Actual placement can require more. Partitioning assumes balanced routing, demand, and data size. Multiple partitions can repeat index definitions and fixed directory or lookup allowance. Cross-partition query overhead and skew need workload measurements.
The Hetzner preset uses 64 GiB RAM, 1.92 TB NVMe, 12 cores, and $85.10 per node per month. Monthly fleet cost is the allocated node count × $85.10. The per-organization figure is the fleet total divided by the number of organizations, so it reflects shared capacity. The per-node rate uses the November 13, 2026 ECB conversion of 1.1052 USD per EUR, rounded to cents before computing totals. ECB exchange-rate history
| Default scenario for 10 organizations | Evidence per organization | Stored counters per organization | Fleet nodes | Fleet cost/month | Average per organization/month |
|---|---|---|---|---|---|
| In Motion, 36 months × 2M incoming events/month | 28,800,000 events | 64,071,489 | 5 | $425.50 | $42.55 |
| At Rest, 3 TB and one current inventory | 520,000 file records | 56,784 | 1 | $85.10 | $8.51 |
| Combined | 28,800,000 events and 520,000 file records | 64,128,273 | 5 | $425.50 | $42.55 |
At Rest budgets 3.31 GB of evidence data and indexes and about 2.50 GiB of cache per organization at 3 TB. In Motion uses about 12.78 GiB of cache per organization. Combined uses about 15.29 GiB per organization, so two organizations fit under each node's 31.5 GiB cache budget. Counter totals are estimates. At 3 TB, the file counter groups still reach their cardinality caps at 40% saved because saved files fill the existing categories, locations, audiences, and flags.
Calibration and calculations
The simulator uses allocated bytes from a small read-only local MongoDB 9.0.4 fixture. The shared collection had 35,114 records, 74.49 MB logical BSON, 48.09 MB allocated data, and 180.43 MB allocated indexes. Prefix search used 133.71 MB. The 197,718 counter cells used 20.42 MB allocated data and 16.33 MB allocated indexes. The old page_subject_all_views tree is excluded from the sizing assumptions. Disk allocation and physical index assumptions use the shared schema.
| Calibration input | In Motion event rows | At Rest file rows |
|---|---|---|
| Fixture records in the matching mode and view | 13,019 | 15,091 |
| Average logical BSON bytes per record | 2,155.38 | 2,094.34 |
| Average indexed search prefixes per record | 59.30 | 57.02 |
| Average flags per record | 0.540 | 0.953 |
The mode-specific sample excludes 5,154 In Motion content rows and 1,850 At Rest event rows from the synthetic fixture. The current demo and Scale Lab generate these secondary views, and the current server uses shared CountEx maps. The simulator represents the planned workload split. The deployed app still uses one workspace database with source and view partitions. The compact file counters cover inventory summaries. Per-file evidence queries still use evidence indexes, and additional precomputed file drill-downs or per-grant counters would need their own sizing. Source scopes (server/model.js) · Demo fixture (server/demo-data.js) · Scale Lab profile (scale-lab/profile.js) · Counter definitions (server/counters.js)
- Evidence indexes. The shared
recordsschema budgets 22 physical indexes with search enabled. Twenty are scalar, one stores lifecycle flags, and one stores search prefixes. A record contributes a scalar key to each scalar index, flag keys with an empty-array allowance, and search keys if enabled. Directory, audit, settings, and workspace metadata add 11 definitions. Each counter generation adds 11 definitions, including five indexes on cells, three on the dictionary, one on the sequence collection, and two on the optional evidence collection. Mongo schema (server/db.js) - Counter entries. Counters estimate distinct cells from contributions, adjustable tuple-use rates, and per-group cardinality caps. Each cell contributes five index keys. Contributions can be coalesced into fewer writes within a batch. The default disk reserve holds the active, preceding, and rebuilding generations.
- Disk. Provisioned bytes = (evidence data and indexes + supporting data + retained counter generations + journal allowance) × (1 + temporary reserve share) ÷ (1 − free-space share). The defaults use a 10 GiB node allowance, 15% temporary space, and 25% free space.
- RAM. The estimate uses the hot subset of index pages and logical document sizes for decompressed data. Of each 64 GiB node, the model allows about 31.5 GiB for WiredTiger cache. The individual machine floor is 16 GiB RAM. MongoDB WiredTiger
- CPU and I/O. Ingest, refresh, rebuild, lookup, and broad counter query demand use editable costs. The model uses a 4-core minimum for machine comparisons. Full hardware sizing should use a representative load with measurements of query latency, IOPS, page/cache behavior, and rebuild throughput. File payload storage, scan connector compute, and document classification compute are outside the database estimate. MongoDB explain results