Cardinality, Volume Tiers & Drivers
Mockomat doesn't just hold mock data — it also holds a model of how much data each table should contain. That model is what makes the board feel like a real schema at real scale: a Plans table sits at a handful of rows, a Customer table at thousands, an AuditLog table at hundreds of millions. The model lives next to your schema and follows it as it evolves.
This page covers the model from the simplest reading ("which chip am I looking at on the board?") down to the power-user surface ("how do I chain drivers and table counts into a formula to forecast next year's data?").
The tier chip
Every table on the modelling board carries a small chip in its header:
| Chip | Range (rows) | Typical archetype |
|---|---|---|
| Singleton | 1 – 10 | Enum-like (Plan, Role, Currency) |
| Seed | 10 – 500 | Curated reference (Country, Tag) |
| Small | 500 – 50 000 | Working set (B2B Customer, Project) |
| Medium | 50 000 – 5 000 000 | Core facts (Order, Invoice) |
| Large | 5 000 000 – 500 000 000 | Events / logs (AuditLog, Telemetry) |
| Firehose | > 500 000 000 | Append-only streams |
The chip's colour follows the tier; a pin or formula glyph next to the label tells you whether the tier was inferred by Mockomat (no glyph) or pinned by you (pin = fixed number, function-symbol = formula).
You don't need to do anything for tiers to appear — Mockomat picks a reasonable default for every new table the moment it lands on the board.


Tier chip on a table card. Click it to open the volume-tier dialog.
Why the tier matters
Two things use the tier in V1:
- The board renders it as a visual cue — at a glance you see which tables are reference data, which are facts, which are telemetry-shaped. No more squinting at attribute lists to guess.
- The forecast layer uses tier comparisons to flag inconsistencies (e.g. a child table can't have more rows than its required parent).
And one thing it unlocks in V2 and beyond:
- The 3D "data city" uses tier as building height. Singleton tables are ground-floor kiosks; firehose tables are skyscrapers. A balanced schema looks like a varied skyline; a problem looks like a single tower dominating the city.
The earlier you set sensible tiers, the more the rest of Mockomat can tell you.
Three ways to resolve a tier
Click any tier chip and the Volume tier dialog opens. The first choice in the dialog is how the tier is resolved:
Auto (default)
The tier is inferred from the FK graph plus a few shape signals on the table's own attributes. You don't touch anything — Mockomat re-computes the tier every time the schema changes.
Mockomat picks the first matching rule from this ladder:
| Rule | Result |
|---|---|
| Table name matches a driver code (see below) | tierOf(driver.value) |
Table has telemetry-shaped attributes (correlationId, traceId, spanId) | Firehose |
Table has createdAt and no inbound FKs (append-only) | Large |
| Table has no FKs in or out (orphan) | Seed |
| Table only receives FKs from reference data | Seed |
| Table has a parent FK — take the parent's tier + 1 step (capped at Large) | matched |
| Fallback | Small |
Auto-mode is right for almost every table. It survives schema evolution and stays in sync with no maintenance.
Constant
Pin the table to a fixed row count. Use this when you know the exact number for a small, curated table:
Plan: 5 (Starter, Pro, Business, Enterprise, Custom)Currency: 180 (ISO 4217)Country: 249
Type the number in the dialog. Mockomat maps it to the matching tier via tierOf(value) — 5 lands in Singleton, 180 lands in Seed.
The pinned value never drifts under recompute. Schema changes don't touch it.
Formula
The most powerful mode. Build a product of factors:
Order = Customer × ordersPerCustomerPerYear × horizonYearsEach factor is one of three kinds:
| Kind | What it means |
|---|---|
| Constant | A literal multiplier (e.g. × 12 for orders/year) |
| Table count | The row count of another table (use a parent table) |
| Driver | The current value of a project-level driver (see below) |
The product collapses to a number, the number maps to a tier, the chip updates. Change one factor and every dependent formula re-evaluates.
Formulas can reference formulas, transitively. Mockomat detects cycles (A references B references A) and falls back to Small with a warning rather than crash.
Drivers — the simulator dial
A driver is a named scalar that lives at the project level. You declare it once and reference it from any formula that needs it.
Open the Manage drivers button from any volume-tier dialog (or directly via the drivers dialog). The default form looks like:
| Field | Example | Notes |
|---|---|---|
| Code | customers | Stable identifier formulas reference. camelCase, immutable. |
| Label | "Active customers" | Display name shown in the picker. |
| Value | 10000 | Current value used in formula evaluation. |
| Unit | "per month" | Display-only annotation. |
| Description | "..." | One-liner explaining what the driver represents. |
Why drivers (instead of more constants)?
Drivers let you describe a model with a few dials instead of hundreds of pinned numbers. Three drivers can drive the entire cardinality of a typical SaaS schema:
customers = 50 000
ordersPerCustomerPerMonth = 4
horizonMonths = 18From those three values, every fact-table formula derives:
Order = customers × ordersPerCustomerPerMonth × horizonMonths
= 50 000 × 4 × 18 = 3 600 000 → Medium
OrderItem = Order × avgItemsPerOrder
= 3 600 000 × 3 = 10 800 000 → Large
Invoice = Order × 1.05 (rough 1:1 + retries)
= 3 780 000 → MediumChange customers to 100 000 and every tier updates with no other edits. That's the simulator.
The 6-driver soft cap
Mockomat recommends at most 6 drivers per project. Past that, the model becomes its own maintenance burden — you end up tuning numbers instead of describing the system.
The cap is advisory, not enforced. If your schema genuinely needs more drivers, the dialog warns but lets you proceed.
Naming conventions
Driver codes that work well in practice:
- Singular noun for "how many of this entity" (
customers,users,tenants). - Per-X-per-Y for ratios (
ordersPerCustomerPerYear,eventsPerUserPerDay). - Horizon for time scope (
horizonMonths,horizonDays).
If a driver code matches a table name (case-insensitive, plural-aware), Mockomat's auto-tier engine uses the driver's value for that table. So a driver called customers and a table called Customer link automatically — change the driver, the Customer tier follows.
What happens on the server
When you save a tier change (any mode), the server:
- Validates the input (no self-cycle, no negative values, no unknown driver references).
- Persists the new
volumeMode+ the matchingvolumeConstant/volumeFormulacolumns on the table. - Triggers a project-wide recompute — every other table that transitively depends on the changed value is re-evaluated.
- Returns the updated table.
The client then reloads the board so any rippled tier changes are visible.
Things to know
- Mock storage is decoupled from cardinality. The tier model is a simulation parameter — Mockomat doesn't materialise 500 million rows when you tier a table as
Large. The runtime answerscount-shaped queries as if the volume were there; pagination serves the actual pool rows. - Tiers ladder by orders of magnitude. Don't agonise over precise numbers; pick the tier that captures the intent and move on.
- Constant > Formula > Auto in pinning weight. Once you pin a tier, schema mutations never touch it. Revert to Auto when you want the system to take over again.
- Driver values are scalars, not distributions. Mockomat intentionally avoids "between 1000 and 5000" ranges in V1 — forecasts stay simple to read.
What's next
- The diagnostic catalogue (coming) flags tier mismatches as warnings: a
seedparent with alargechild, a god-table with too many inbound FKs, an unservable formula. These surface as a city weather indicator on the board. - The 3D data city renders all of this as a navigable spatial scene where height = tier and street weight = relation cardinality.
For the architecture and rollout reasoning, see the public Cardinality Model ADR.