Stock-and-Flow Diagrams: Adding Quantity and Time

By Pritesh Yadav 14 min read

In the last chapters we drew causal loop diagrams (CLDs). They are wonderful for one job: showing which things affect which other things, and in which direction. But CLDs have a quiet weakness. They cannot tell you how much of anything there is, or how fast it is changing. They have no numbers, no units, and no sense of time.

This chapter introduces the tool that fixes that: the stock-and-flow diagram, often shortened to SFD. It adds two things a CLD lacks — quantity (how much) and time (how fast). It is the working heart of a field called system dynamics.

Where this tool came from

System dynamics was founded by Jay Wright Forrester at MIT's Sloan School of Management. He arrived there in 1956 and published the field's founding book, Industrial Dynamics, in 1961. The picture-language he created borrowed its shapes from plumbing — vessels (tanks) and pipeline valves (taps). That is not a coincidence; once you see the diagrams, you will see bathtubs everywhere.

In 1959, two programmers at MIT, Phyllis Fox and Alexander Pugh, wrote the first software that could actually run these models. It was called DYNAMO (short for DYNAmic MOdels), and it stayed the industry standard for about 30 years. Later, friendlier graphical tools took over, which we will meet at the end.

Why a CLD is not enough

A CLD is ambiguous. The very same diagram could match many completely different real-world models, because it never says:

  • What kind of thing each box is — does it pile up, or is it a rate of change?
  • What units each variable is measured in (people? dollars? litres?).
  • What equation connects the variables.
  • Whether an arrow carries material (real stuff moving) or just information (a number being read).

The SFD removes all that ambiguity. It forces you to label the type of every element, give it units, and write an equation. As we saw with feedback loops in earlier chapters, structure causes behaviour — and the SFD is how we write that structure down precisely.

The two main characters: stocks and flows

Donella Meadows, in Thinking in Systems (2008), defines a stock plainly:

"A stock is just what it sounds like: a store, a quantity, an accumulation of material or information that has built up over time." She adds the precise version: "Stocks, then, are accumulations, or integrals, of flows." A stock is the system's memory of every flow that has ever happened.

Stock
A quantity that piles up or drains over time. The "noun" of the system. You can measure it at a single frozen instant. Its units never contain "per time." Examples: water in a tank (litres), money in an account (dollars), active customers (people), CO2 in the air (gigatonnes).
Flow
A rate that adds to or removes from a stock. The "verb" of the system. Its units always contain "per time." Examples: faucet rate (litres/minute), deposits (dollars/month), new signups (people/month). A flow cannot exist without a stock to fill or drain.
Inflow
A flow that adds to a stock (births, deposits, signups, emissions).
Outflow
A flow that removes from a stock (deaths, withdrawals, churn, absorption).
Analogy: The speedometer and the odometer. A flow is the speedometer — it tells you your rate right now (60 km/h). A stock is the odometer — it shows the total distance ever travelled. A falling speedometer (slowing down) does not mean the odometer goes down. You are still moving forward; just more slowly. Confusing these two is the single most common mistake in this whole subject.

The temporal test (how to tell them apart)

Whenever you are unsure whether something is a stock or a flow, ask one question: "If time stopped right now, would this thing still exist?"

  • Stocks persist. Stop time and the water is still sitting in the tub.
  • Flows vanish. A "faucet rate" needs time passing to mean anything. Freeze time and there is no rate at all.

A second quick check: stocks have units with no "/time" (dollars); flows have units with "/time" (dollars/month).

Common mistake: Calling "profit" a stock. Profit is a flow (dollars/year). The stock it feeds is retained earnings. Likewise, "interest rate" is not a stock — it is a constant that helps calculate a flow. If you model it as a stock, it will wrongly pile up over time.

The four notation elements

Every SFD is built from just four shapes:

  1. Stock — drawn as a rectangle (box). The accumulation.
  2. Flow — drawn as a thick pipe with a valve (a little tap or bowtie) on it. The valve sets the rate. Arrows into the box are inflows; arrows away from it are outflows.
  3. Cloud — a cloud shape at the end of a pipe where it crosses the edge of your model. A source cloud is an infinite supply outside the model; a sink cloud is an infinite disposal outside it.
  4. Information connector — a thin curved arrow from a stock or auxiliary to a valve. It says "the value of this thing influences that flow rate." It carries information, not material.
Analogy: Clouds are the edge of the map. When you draw a map of your neighbourhood, it has a border, and everything beyond it is simply "not drawn here." A cloud is that border. It is not ignorance — it is a deliberate decision about what is inside and outside your question.

One more element you will need constantly:

Auxiliary variable (also called a converter)
A small circle that calculates an intermediate value used by a flow equation. It never stores anything (not a stock) and never directly changes a stock (not a flow). Examples: a churn rate (5%/month), or "fraction of market untapped" = (total market − customers) / total market. Freeze time and an auxiliary disappears, just like a flow, because it only computes a value.

The picture: a bathtub

This is the founding example of the whole field.

  tap supply                              sewer
   (cloud)                              (cloud)
      \                                    /
       \   faucet                drain    /
        \   rate                  rate   /
   ~~~~~~|>--[X]--> +----------+ --[X]-->|~~~~~~
                    |  WATER   |
                    | IN TUB   |   (stock, litres)
                    +----------+
        [X] = valve     |> = inflow pipe

One stock (water, in litres). One inflow (faucet, litres/minute) coming from a source cloud. One outflow (drain, litres/minute) going to a sink cloud. The level changes by this rule each moment:

Water(next) = Water(now) + dt × (faucet rate − drain rate)

Here dt is a small time step (say one minute). This is the Euler method — the simplest way software adds up a flow over time. The smaller the step, the more accurate the result.

Example: If the faucet runs at 2 L/min and the drain at 1 L/min, water rises at 1 L/min. If both equal 1 L/min, the level holds perfectly steady even though water is moving the whole time. Meadows put it nicely: "There's more than one way to fill a bathtub" — you can raise the level by opening the tap or by closing the drain.

The mistake everyone makes

John Sterman at MIT studied how people reason about bathtubs. He found that most highly educated adults — including MIT students — get it wrong. The error is called the correlation heuristic: people draw the stock graph as a copy of the flow graph. They expect the water level to fall when the faucet is turned down. But the stock is the accumulated area under the net-flow curve, not the flow itself. As long as inflow still exceeds outflow, the level keeps rising even while the inflow is dropping.

Example: CO2 in the atmosphere. Emissions add roughly 40 gigatonnes/year; nature absorbs about half. The net inflow of ~20 Gt/year keeps the stock climbing. Even if humanity cut emissions in half tomorrow, net inflow stays positive and the concentration keeps rising. The stock only stabilises when emissions fall below absorption. Confusing "we slowed the rate of increase" with "we lowered the level" is the bathtub mistake applied to climate policy.
Key takeaway: A stock is the integral (running total) of its net flow. It can only change as fast as the flows allow, so it can never jump instantly. This is why Meadows says stocks act as "delays, buffers, or shock absorbers." Flows are volatile; stocks are slow and stable.

Worked example: a savings account (a reinforcing loop)

Stock: account balance (dollars), starting at $1,000. Inflows: a $200/month deposit, plus interest earned. Outflow: $50/month of withdrawals. Auxiliary: a monthly interest rate (0.5%/month, i.e. 6%/year).

The interesting part is the interest. We draw an information connector from the balance stock back to the interest valve, because interest = balance × rate. The bigger the balance, the more interest; the more interest, the bigger the balance. That is a reinforcing feedback loop, and it bends a straight line into a curve that accelerates upward — exponential growth.

The famous Rule of 72 says money doubles in roughly 72 ÷ (yearly % rate) years: about 12 years at 6%, about 7.2 years at 10%. You can build this in a spreadsheet with five columns: Period | Balance start | Deposits | Interest | Balance end.

Worked example: a customer base (a balancing loop, the "leaky bucket")

Stock: active customers (people), starting at 0. Inflow: new signups (100 people/month). Outflow: churn = active customers × churn rate (5%/month). The churn valve reads from the customer stock, so the bigger the base, the more customers leak away — a balancing feedback loop that resists growth.

Analogy: A bucket with a hole. You pour signups in the top; churn leaks out the bottom. As the bucket fills, the leak grows (because churn is a percentage of what's inside). Eventually inflow equals outflow and the level holds — even though both are still flowing.

The equilibrium is easy: signups = churn, so 100 = customers × 0.05, which gives a steady state of 100 / 0.05 = 2,000 customers. The diagram makes both levers obvious: to grow past 2,000 you must either pour faster (more signups) or plug the hole (lower the churn rate).

Converting a CLD into an SFD — 7 steps

  1. Assign units to every variable. Anything measured "per time" is a candidate flow.
  2. Identify the stocks — the things that persist when time stops.
  3. Identify the flows that raise or lower each stock; mark them inflow or outflow.
  4. Connect stocks to flows with information connectors where a stock's level drives a rate.
  5. Add auxiliaries — constants (market size) and calculated intermediates (fraction untapped).
  6. Write an equation for every flow and auxiliary, and check the units balance.
  7. Add clouds at the model boundary, so every flow starts and ends somewhere.
Common mistake: Labelling boxes in a CLD as "stocks" without drawing pipes, valves, clouds, and equations, then calling it an SFD. The real test: can you write an equation for every valve? If not, it is an incomplete SFD with no computational meaning.

Stock versus flow at a glance

QuestionStockFlow
Survives if time stops?YesNo
UnitsNo "/time" (dollars)Has "/time" (dollars/month)
Shape on diagramRectanglePipe with a valve
GrammarNounVerb
ExampleRetained earningsProfit per year

Material flows versus information flows

This distinction is real, not cosmetic. Material flows are conserved — water that leaves the tub goes somewhere. Information flows are not conserved — telling the interest formula that the balance is $5,000 costs nothing and depletes nothing. Software draws material as thick double-line pipes and information as thin single arrows. A CLD uses the same arrow for both, which is exactly why it is ambiguous.

Common mistake: Accidentally drawing a material pipe where you meant an information connector. Now you have a second stock-to-stock transfer draining one box to fill another — usually not what you intended. Also: never let units clash. A flow in "people/month" cannot pour into a "dollars" stock. Unit checking is your main debugging tool.

Behavior-over-time (BOT) graphs

A BOT graph plots a stock (or flow) on the vertical axis against time on the horizontal axis. It is the main output of running a model. Six classic shapes recur:

 Linear     Exponential   Goal-seeking   S-curve
   /            |  /         \              __
  /             | /           \__         _/
 /              |/               '---     /
-----        --------         --------  -/-----
  Oscillation: /\  /\  /\   Overshoot+collapse: /\
              /  \/  \/  \                      /  \___

Linear growth comes from a constant net inflow. Exponential growth (J-curve) comes from a reinforcing loop, like the savings account. Goal-seeking decay comes from a balancing loop. An S-curve appears when reinforcing growth runs into a balancing limit, as in the customer base or market saturation. Oscillation and overshoot-and-collapse appear when feedback is delayed — the system overshoots before the correction arrives (think fisheries that boom then crash).

Common mistake: Reading a BOT graph as if it explains itself. The graph shows what happened; it never shows why. Two utterly different systems can produce identical S-curves. To know whether you can change a behaviour, you must trace the loops in the SFD — structure, not the picture, holds the answer.

From engineering to the boardroom: Senge's contribution

Peter Senge, Forrester's colleague at MIT Sloan, popularised all this for managers in The Fifth Discipline (1990). He added no new notation, but he named recurring SFD patterns as systems archetypes — Limits to Growth, Fixes That Fail, Shifting the Burden, Tragedy of the Commons, Escalation, and Success to the Successful — and framed the "learning organization" that uses feedback understanding to escape short-term thinking. We will meet these archetypes again in later chapters.

Tools you can use

  • STELLA — the first icon-based, drag-and-drop modelling tool, built by Barry Richmond at Dartmouth and released in 1985. He won the Jay W. Forrester Award in 1989. Friendly and widely used in teaching.
  • Vensim — by Ventana Systems, released 1991. Strong on calibration, optimization, and sensitivity testing. Its free PLE (Personal Learning Edition) is great for students.
  • InsightMaker — free, open-source, runs in a browser with nothing to install. An excellent zero-cost starting point.
  • A spreadsheet — perfectly adequate for 1–3 stock models. Use columns Time | Stock_t | Inflow | Outflow | Net | Stock_next, set a small dt, and copy the formula Stock_next = Stock_t + (Inflow − Outflow) × dt down the page. Plot the stock column to get a BOT graph.
Tip: Do not wait for fancy software. Build your first model in a spreadsheet. Over-focusing on tools delays the thing that actually matters — understanding how accumulation works. The five-column trick above will teach you more than any menu.

Key Takeaways

  • A stock-and-flow diagram adds what a CLD lacks: quantity and time, by labelling the type of every element, assigning units, and writing equations.
  • A stock accumulates and survives if time stops; a flow is a rate (units "/time") and vanishes if time stops. Use the temporal test and the unit test to tell them apart.
  • Mathematically, a stock is the integral of its net flow (Stock_next = Stock_now + dt × net flow). Stocks change slowly and act as buffers and delays.
  • The famous bathtub error is treating the stock graph as a copy of the flow graph; in reality a stock keeps rising while inflow exceeds outflow, which is why slowing emissions does not lower CO2 levels.
  • Distinguish material flows (conserved, thick pipes) from information connectors (not conserved, thin arrows); mixing them causes structural errors.
  • Structure generates behaviour — read the loops in the SFD to understand why a BOT graph has its shape, then change the structure to change the outcome.

Continue reading