See How PostgreSQL Works: A Hands-On Tour of PGSimCity
Open PGSimCity and in fifteen minutes you will have watched a query travel from client to commit, broken a database’s buffer pool on purpose, and seen exactly why one forgotten transaction bloats a table forever. No install, nothing to sign up for.
TLDR:
- Open the city in any WebGL2 browser and press
Tfor the 14-chapter guided tour. - Press
Enterto trace a Non-HOT UPDATE in slow motion through buffers and WAL. - Run the Scenarios menu: Cache thrash, Checkpoint storm, The work_mem cliff, Long-running transaction.
- Press
Gto walk at eye level;Eoperates levers;?shows every key and color. - Reset anytime with
R.
Prerequisites: any current browser with WebGL2. Running locally instead needs Node.js 20+ (or 22+) and npm run dev.
Step 1: Take the guided tour
Press TThe tour walks fourteen chapters following one connection from the client sky down through planning, the shared-buffers pool, WAL, checkpoints, vacuum, and replication. This is the fastest way to learn the city’s geography: postmaster, sixteen backends whose lighting is their state, the storage excavation where heap files sit as fields of 8 KiB pages.
Step 2: Trace one statement in slow motion
Press Enter → pick Non-HOT UPDATE → press , to slow playbackWatch the statement unfold as parse, rewrite, plan, execute, then follow it into the buffer pool, watch it create WAL, and wait with it at commit. Slowed to 0.1x, you can finally see what normally happens in microseconds.
Pro tip: press
/(or Ctrl/Cmd+K) for the command palette. It searches every component, setting, and scenario by name, which beats hunting menus once you know what you want to see.
Step 3: Break it on purpose
Scenarios menu → Cache thrash → then Checkpoint stormCache thrash shrinks shared_buffers below its manual minimum so the clock sweep races and backends evict their own victims mid-read. Checkpoint storm spins up the checkpointer’s flywheel and floods the WAL district with full-page writes after each fsync shudder. These two scenarios explain most mystery latency spikes in production databases.
Step 4: Watch the three classic trade-offs
Run Long-running transaction and the xmin horizon blade sinks red: autovacuum still visits the table but reports zero removable rows while bloat continues, the cleanest demonstration anywhere of why one idle-in-transaction session hurts everything. Then run The work_mem cliff, where sorts spill to disk at 2 MiB and fit at 4 MiB without replanning. Finally set synchronous_commit to off, watch backends stop waiting in commit_wait, and read what you just traded away.
Step 5: Get on the ground
Press G → walk with WASD → press E near levers and doorsAt eye level a buffer frame that looked like one tile becomes a structure over your head. E operates the autovacuum lever or the postmaster door; ? shows the full key map and the semantic color legend (WAL is amber, dirty pages red, vacuum violet); keys 1 through 8 jump between districts.
Step 6: Check the model against the real thing
The Machine section is a separate psql workbench running PGlite, real in-memory PostgreSQL compiled to WebAssembly, opt-in with one click. Plans, counters, and errors come from actual Postgres; the visible interior comes from the model, and each surface labels which is which.
Cleanup
Nothing persists in the browser; press R to reset all settings and Esc closes overlays. Locally:
rm -rf node_modules dist # optional, after stopping the dev serverIf it breaks: a blank screen means WebGL2 is missing or disabled; try current Chrome, Edge, or Firefox. Touch controls are only verified in Chrome’s mobile emulation. And remember the numbers are scaled for human eyes; the README’s “How much to trust this” section lists exactly which simplifications are deliberate.
Related TMFNK Content
- Merges and Joins: From SQL to Stata The same visual-first approach to SQL concepts, one level up from storage internals.
- modelmap Another explorable machine room: paste a Hugging Face id and walk through a neural network’s architecture.
- LLM Visualization by Brendan Bycroft Interactive transformer internals for when the black box you want opened is a model, not a database.
Crepi il lupo! 🐺