Stock / Flow Separation Check¶
Stock–flow separation check — instantiates Dimensional Consistency Check
Separates accumulated stocks from the flows that fill or drain them — balances from rates, prevalence from incidence — so a level is never compared directly with a speed.
Stock / Flow Separation Check targets one specific and pervasive dimensional confusion: mixing a stock — an accumulated quantity that exists at a point in time — with a flow — a rate at which that quantity changes over time. A bank balance is a stock; income is a flow. Water in a reservoir is a stock; the inflow is a flow. Its defining feature is enforcing the time dimension: a stock has no "per unit time" and a flow always does, so the two can never be added, subtracted, or directly compared without an interval to connect them.[1] The confusion is seductive because both often wear the same nominal unit — dollars, people, litres — and only the hidden time basis distinguishes them. This check makes that basis explicit and rules on what may legitimately be done with each.
Example¶
An operations lead reviews a warehouse dashboard that reports "inventory: 8,000 units" beside "shipments: 2,000 units" and computes a "coverage" number by dividing them. The separation check stops the division as written. Inventory is a stock — units sitting on shelves right now, dimension [units]. Shipments is a flow — units leaving per week, dimension [units / week]. The bare ratio 8,000 / 2,000 = 4 is not "4" of anything until the flow's time basis is restored: 8,000 units ÷ 2,000 units-per-week = 4 weeks of coverage. The answer is a duration, and only the stock/flow distinction reveals that the result is measured in time at all.
The check also catches the reverse error elsewhere on the dashboard, where a one-time write-off (a stock adjustment) is added to a monthly holding cost (a flow) to report a single "cost" figure — two quantities that cannot be summed without choosing an interval over which the flow accumulates. In each case the output is the same: the quantities are tagged stock or flow, the illegitimate operation is blocked, and the legitimate one — the interval that connects them — is named.
How it works¶
- Tag each quantity stock or flow. Ask whether it exists at an instant (stock) or accrues over time (flow); the presence or absence of a hidden "per unit time" is the test.
- Enforce the compatibility rule. Stocks and flows cannot be added or directly compared; they relate only through an interval — a flow integrated over time yields a stock change, a stock divided by a flow yields a duration.
- Restore the time basis in every ratio. When a stock and flow are combined, carry the time unit through so the result's dimension (often a duration) is explicit rather than a bare number.
- Watch for shared nominal units. Because both may read "dollars" or "units," rely on the time basis, not the label, to tell them apart.
Tuning parameters¶
- Time-basis granularity — the interval flows are expressed over (per day, per month, per year). Mismatched intervals across flows produce their own errors; picking a consistent one is the key dial.
- Tagging strictness — whether every quantity is explicitly labelled stock or flow, or only the suspicious ones. Full tagging catches more; selective tagging is faster.
- Accumulation window — for operations that convert a flow to a stock, the interval chosen to integrate over, which sets the magnitude of the result.
- Boundary handling — how opening and closing stock levels are treated when reconciling a flow across a period.
When it helps, and when it misleads¶
Its strength is catching a confusion that is everywhere and rarely noticed: budgets that add one-time to recurring, dashboards that divide a level by a rate and report a meaningless number, epidemiology that treats prevalence (a stock) as incidence (a flow). Because the error hides behind a shared unit, an explicit stock/flow pass is often what surfaces it.
Its limit is scope — it governs the time dimension specifically and will not catch non-temporal errors like a wrong denominator or a currency mismatch. It can also mislead when a quantity is genuinely ambiguous or measured over an unstated window, tempting a false-precise tag. The discipline is to insist on an explicit time basis for every flow, treat any quantity whose interval is unstated as unresolved rather than guessing, and pair the check with other dimensional tests for the non-temporal mismatches it does not see.
How it implements the components¶
quantity_semantics— its core distinction: whether a quantity means an accumulated level or a rate of change, a difference in construct that a shared unit conceals.operation_compatibility_rule— it rules that stocks and flows may not be added or directly compared, only related through an interval.scale_basis— it makes the time basis of every flow explicit (per day, per month), which is precisely the basis the confusion leaves implicit.
It does not carry the money-specific constructs of nominal/real or cash/accrual (that is Finance / Accounting Unit Check), nor divide a total by a population to compare sizes (that is Per-Capita or Per-Unit Conversion); it isolates the stock-versus-flow, level-versus-rate distinction.
Related¶
- Instantiates: Dimensional Consistency Check — the archetype focused on the time dimension, where levels and rates are wrongly treated as the same kind of quantity.
- Sibling mechanisms: Finance / Accounting Unit Check · Per-Capita or Per-Unit Conversion · Cross-Scale Transfer Review · Dimensional Analysis Table · Dimensionless Ratio Construction · Engineering Equation Sanity Check · Model Input / Output Contract · Normalized Metric Design · Spreadsheet Unit Audit · Unit Check · Unit Conversion Workflow
References¶
[1] The stock-and-flow distinction is foundational to system dynamics: a stock is the accumulation (the level in a tank), a flow is its rate of change (the pipe), and the two are linked only by integration over time. Confusing them is a dimensional error, since a flow carries a time unit a stock does not. ↩