Why bottlenecks matter:
A resource chain with no constraint anywhere is a system with no decisions in it as the player just watches numbers go up. A bottleneck is what forces a choice: build more storage, add a splitter, slow the source, accept some waste. This is why Factorio players obsess over throughput ratios, why Anno's real late-game limit is shipping routes rather than production, and why RimWorld makes colonist labor and not materials the actual scarce resource. economy design doesn't treat bottlenecks as bugs to remove; it treats where to place one as the core design decision. This project is a small, testable version of that same instinct.
The Chain
Forest → Sawmill → Plank storage → Workshop → Furniture storage → sold for gold
[Stock/flow diagram]

Built as stocks (things with a capacity) and flows (rates that move between them) the standard for simulating any resource economy.
Bottleneck by design
Sawmill produces faster than the Workshop consumes on purpose so Plank storage was expected to fill up and become the constraint.

Simulated tick-by-tick, not solved with algebra
Every row = one tick, reading only the row above. Each flow's output is a MIN() of three honest limits: its own max rate, available input, and downstream storage room. The bottleneck wasn't scripted it emerged from those three constraints.


What I found
-
Plank storage saturates around tick 20 and the Sawmill self-throttles to match consumption smoother than the hard stop-start I predicted
-
Gold grows at a steady 5/tick once the system stabilizes
-
Raising the storage cap alone doesn't fix it , it just delays saturation (tested: 20 → 40 cap, saturation point moved tick 20 → 40, same final Gold)

How i landed on these numbers
-
Worked backward from one goal: a single, legible bottleneck that saturates within a readable ~20-tick window not too fast to see coming, not so slow it never shows up in a demo.
-
Force a surplus. Sawmill output must exceed Workshop consumption, or nothing ever saturates. → sawmill_rate (2) > workshop_rate × planks_per_furniture (1×1=1) → surplus = +1 plank/tick
-
Make sure wood can't be the limiter instead. Sawmill's max wood draw = sawmill_rate × wood_per_plank = 2×2 = 4/tick. → Set gather_rate = 5, comfortably above 4, so Wood stays a non-issue at baseline (confirmed in Scenario A by pushing Sawmill rate further is what finally exposes this margin)
-
Keep the recipe cheap. If planks_per_furniture were high, the Workshop would starve for input before storage ever filled (confirmed later in Scenario D). Set to 1 to keep storage the binding constraint and not recipe cost
-
Size the cap to the target window. With a known surplus of +1/tick, storage of size N saturates at roughly tick N. → Wanted ~tick 20 → plank_cap = 20
-
Remove Furniture as a second bottleneck. Sell rate just needs to clear Workshop's max output (1/tick). → Set sell_rate = 2, comfortable headroom
-
Each number is a direct answer to "what does this need to be true for the bottleneck to land exactly where I want it" not a guess tuned by trial and error
Stress-testing the numbers (4 scenarios)
The Real Question
The obvious fix or decision player will make is splitting the output + 2nd Workshop and that currently dominates every other fix whenever the player can afford it , not a real decision yet.
Workaround: Player can sell excess planks in the market to start an another source of income till
the need to use for planks into any other final product or finishing a quest to make 200 furnitures
The right answer depends on what the player is short on.
Next steps
-
Stock/flow model + tick-by-tick simulation - Done
-
Stress-test baseline assumptions with 4 scenarios - Done
-
Model competing fixes with distinct cost currencies
-
Build in UE5 with DataTables driven by these exact numbers
-
Playtest and compare real data against this spreadsheet's predictions