PGSimCity: a walkable 3D model of PostgreSQL internals
An explorable 3D city that shows how Postgres actually works. PGSimCity An explorable 3D city that shows how PostgreSQL actually works.** PGSimCity turns a PostgreSQL cluster into a city you can inspect, walk through, and break.
At a glance
- What is it?
- PGSimCity renders a PostgreSQL cluster as a 3D city you can tour, stress and break. It is a teaching model, not an emulator, and its own README says the animation must not be used as numeric version evidence.
- Who is it for?
- Adopt PGSimCity for onboarding engineers who can write SQL but have never watched a checkpoint, and for anyone preparing to explain shared_buffers, vacuum or synchronous_commit without a whiteboard. Do not adopt it as a sizing tool or as evidence of PostgreSQL 18 numeric behaviour: the README states the buffer sample is a fixed 32-frame ring and that the animation must not be used as numeric version evidence until the model is aligned.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The audience PGSimCity is written for
The README names its reader precisely: engineers who are good at their job and have never had to operate a database. That is a real gap. A backend developer can write correct SQL for years without ever seeing why a checkpoint spikes latency, why one forgotten transaction bloats a table indefinitely, or what synchronous_commit is charging them. Those are operational facts that usually arrive through an incident, not a tutorial.
PGSimCity's answer is spatial. A PostgreSQL cluster becomes a city with districts, and each district is a component with a fixed location. Connections arrive in a client sky to the north. The postmaster forks one backend per connection and, per the README, never touches your data. Sixteen backends sit in a row, and their lighting is their state, including idle in transaction. The buffer pool sits beside wal_buffers, the ProcArray, the lock table, CLOG and the buffer mapping table. Below the excavation, the data directory, storage is laid out as 8 KiB heap pages, B-trees drawn as actual trees, TOAST, the FSM, the visibility map, the OS page cache and the disks.
It is not a general PostgreSQL course. It is a model of one cluster, aimed at the person who has to reason about memory, WAL and vacuum but has never had to page someone at 3 a.m. about them.
How the city maps onto a running cluster
The layout is the architecture. The WAL district sits east: backends and the walwriter write WAL into pg_wal, the archiver copies completed segments, and walsenders independently stream WAL as it is generated. The maintenance yard is west, holding the checkpointer, the background writer, the autovacuum launcher and its workers. Standbys sit south with two independent walreceivers, startup processes replaying WAL, and the lag on each stream. The continuity quarter on the outer east and south covers the WAL archive, base backups, point-in-time recovery, delayed replay, leader lease and rejoin machinery. Above the backends, the Query lab unfolds a selected backend's statement through parse, rewrite, plan and execute.
Colour carries meaning rather than decoration. WAL is amber, dirty pages are red, clean pages are blue, vacuum is violet, checkpoints are pink, the background writer is teal, replication is orange, storage is green, indexes are aqua and locks are red. Once you have learned the palette, you can read a scene without reading a legend.
The buffer pool is where the model is most explicit about its own limits. It holds up to 1,024 representative frames, with 256 active at the 2 GiB model default, while PostgreSQL 18 defaults to 128 MiB. The README states that the current TypeScript buffer sample still uses a fixed 32-frame ring, and calls that a disclosed historical simplification for the animation rather than PostgreSQL 18's ring-sizing rule. In the real engine, the bulk-read strategy starts at 256 KiB and grows with io_combine_limit times effective_io_concurrency, subject to its caps. The project says the animation must not be used as numeric version evidence until the model is aligned. That sentence is the most useful thing in the README.
Installing PGSimCity and running your first scenario
The fastest route needs no install at all: the README links a live city at nikolays.github.io/PGSimCity. If you want to run it locally, the repository is a Vite project. The package.json declares the package name pgsimcity, type module, and engines of node ^20.19.0 or >=22.12.0, so check your Node version before anything else.
Clone the repository and install dependencies:
git clone https://github.com/NikolayS/PGSimCity.git
cd PGSimCity
npm installStart the development server with the dev script, which runs Vite:
npm run devFor a production build and a local preview, the package defines two more scripts. The build step runs vite build, and preview serves the output on port 4173:
npm run build
npm run previewThe preview script is defined as vite preview --port 4173, so the served city appears on that port. The package also exposes a typecheck script (tsc --noEmit), a test script (vitest run) and a layout verification script (node tools/verify-hud-layout.mjs) if you want to confirm a checkout is healthy before teaching from it.
Once the city is up, the README's suggested first moves are keyboard driven. Press T for the 14-chapter guided tour, which follows one connection from the client through planning, caching, WAL, checkpoints, vacuum and replication. Press Enter to trace a single statement, then pick Non-HOT UPDATE and slow the playback down; the README says that exposes where the statement enters the buffer pool, creates WAL and waits to commit. From the Scenarios menu, Cache thrash sets shared_buffers to 16 MiB, below the manual control's 128 MiB minimum, so the clock sweep races and backends write their own dirty victims before they can read another page.
What the scenarios actually demonstrate
The scenario list is where the teaching happens, and each one is tied to a mechanism rather than a mood. The work_mem cliff uses fixed Sort and HashAggregate nodes that spill at 2 MiB and then fit at 4 MiB without replanning. The private reservoirs, base/pgsql_tmp, temp counters and latency breakdown show the consequence. That is a compact demonstration of a point that is hard to convey in prose: the plan does not change, the memory does.
Long-running transaction is the other scenario worth naming. The xmin horizon blade sinks and goes red. Autovacuum still travels to the tables but reports zero removable rows while the sessions table keeps bloating. Releasing the transaction lets cleanup begin again. If you have ever explained why a long-lived idle transaction is dangerous, this is the diagram you were drawing badly on a whiteboard.
Checkpoint storm shows the checkpointer's flywheel spin up, the fsync phase shudder, and a wall of full-page writes flood the WAL district after each checkpoint begins. Setting synchronous_commit to off makes backends stop waiting in commit_wait, and the README's instruction is to then read what you traded away. Slow replay shows sent_lsn, write_lsn and the rest of the replication positions moving at a controlled pace.
Two of these deserve a caution. The README states that the deterministic suite pins the model's scaled WAL trigger approximation as max_wal_size divided by (1 + checkpoint_completion_target) at every call site, while PostgreSQL 18 computes the moving threshold in whole WAL segments through ConvertToXSegs(max_wal_size_mb) divided by (1 + checkpoint_completion_target), and therefore rounds it. The suite also pins cache hit ratio as blks_hit / (blks_hit + blks_read) and the clock-sweep usage_count cap at 5. Those are the model's rules, disclosed as such, not the engine's.
Where the model stops being PostgreSQL
The README is unusually direct that the 3D city is a model, not an emulator. No PostgreSQL source code runs in that city, and the numbers are scaled so a human can watch them. The opt-in Query flow and the machine directory can run PGlite, a real in-memory PostgreSQL compiled to WebAssembly. That distinction matters more than any single scenario: if you want real query results, you are using a different part of the project than the city.
The accessibility boundary is stated just as plainly. The PostgreSQL lessons have keyboard and text-first routes, including a city architecture description generated from the layout, but the 3D scene and first-person walk have no nonvisual equivalent. The README points to ACCESSIBILITY.md for what is covered and what remains irreducibly spatial. A team that needs a screen-reader-friendly teaching artifact should read that file before committing to the city as the primary format.
Touch controls are a second known gap: the README says they have been verified only in Chrome's mobile emulation. And the version line is 0.x, described as early and moving. The package.json version is 0.58.1 while the most recent release listed is v0.40.0, which is a reminder to read the changelog rather than assume a stable surface. None of this makes the project untrustworthy. It makes it a teaching aid with a stated accuracy budget, and the budget is the thing to check against whatever lesson you intend to teach.
PGSimCity compared with reading the PostgreSQL source
The obvious alternative is not another visualization. It is the PostgreSQL documentation and the REL_18_STABLE source tree, which PGSimCity itself treats as the reference. The project states that it targets the PostgreSQL 18 major line, that PostgreSQL 18.4 is the reviewed reference release against which its claims were verified, and that mechanism claims follow the REL_18_STABLE source. The difference in approach is that the source tells you exactly what happens and gives you no intuition about magnitude or sequence, while PGSimCity gives you sequence and magnitude at the cost of exactness.
That trade is the whole product. Reading xlog.c will tell you precisely how the checkpoint threshold rounds; it will not show you a checkpointer's flywheel spinning up or a wall of full-page writes arriving after a checkpoint begins. Watching the city will give you the shape of the event; it will not tell you what your cluster will do at your WAL volume. A team that wants both should use the city to build the mental model and the source to check any number that ends up in a design document.
There is also a maintenance dimension to the comparison. The source tree is versioned by the PostgreSQL project; PGSimCity is a single-author educational project whose README describes four review rounds, three specialist reviews comparing PostgreSQL correctness against postgresql.org/docs and the source rather than memory, plus a separate audit that treated buildings, adjacencies and animations as claims, with every finding independently checked by a reviewer tasked with refuting it. That process is described in the README, not verified here. It is the kind of process claim you should weigh by reading the commit history, which the README says records the mistakes found and fixed.
Licence, maintenance and what upgrading costs you
PGSimCity is licensed Apache-2.0, and the package.json repeats that identifier. The README adds a separate legal note that is worth reading in full: the project is an independent, non-commercial educational visualization and is not affiliated with, sponsored, endorsed or approved by Electronic Arts Inc. It states that it contains no SimCity code, assets, artwork, logos, characters, audio or game content. The repository also carries a NOTICE file, which is the conventional place for attribution material under Apache-2.0. If you plan to reuse assets or redistribute a build, read LICENSE and NOTICE together rather than relying on the identifier alone. This is a description of what the files say, not legal advice.
On maintenance, the last push to the default branch was on 2026-08-06, and the repository is not archived. The release history around that date is dense: v0.39.5, v0.39.6 and v0.40.0 all landed on 2026-08-05 and 2026-08-06. The release titles are unusually candid. v0.39.5 is titled a saved setting could stall the city, and v0.40.0 is titled nineteen defects, and a moon. That tells you fixes arrive in batches and that the changelog is the place to look before pinning a version.
The upgrade cost is mostly the cost of re-verifying what you teach. Because the model deliberately approximates engine behaviour and the README flags at least one unaligned area, a version bump can change a scenario's numbers or a district's appearance. If you build a curriculum on top of PGSimCity, pin a commit, keep the changelog next to your lesson notes, and re-check any scenario whose point depends on a specific figure.
Editorial conclusion
Adopt PGSimCity for onboarding engineers who can write SQL but have never watched a checkpoint, and for anyone preparing to explain shared_buffers, vacuum or synchronous_commit without a whiteboard. Do not adopt it as a sizing tool or as evidence of PostgreSQL 18 numeric behaviour: the README states the buffer sample is a fixed 32-frame ring and that the animation must not be used as numeric version evidence until the model is aligned. Before you rely on it in a class, verify the specific mechanism you plan to teach against the REL_18_STABLE source the project cites, and check whether the Query lab's PGlite path is enabled in the build you are using, since the 3D city itself runs no PostgreSQL code.
Frequently asked questions
What is PGSimCity?
It is an explorable 3D city that shows how PostgreSQL works, built as an independent, non-commercial educational visualization of PostgreSQL internals. The README describes it as a model of PostgreSQL rather than an emulator: no PostgreSQL source code runs in the 3D city.
Do I need to install anything to try PGSimCity?
No. The README links a live city at nikolays.github.io/PGSimCity and states that no install is required. Running it from source is a Vite project with npm run dev, npm run build and npm run preview.
Does PGSimCity run a real PostgreSQL instance?
Not in the 3D city. The README states that the opt-in Query flow and the machine directory can run PGlite, a real in-memory PostgreSQL compiled to WebAssembly, while the city itself runs no PostgreSQL code and scales its numbers so a human can watch them.
Can I use PGSimCity to predict how my own cluster will behave?
The README says the animation must not be used as numeric version evidence until the buffer model is aligned, and notes that the current TypeScript buffer sample uses a fixed 32-frame ring rather than PostgreSQL 18's ring-sizing rule. Use it to build intuition about sequence and mechanism, not to size a production system.
Is PGSimCity accessible to screen reader users?
Partially. The README says the PostgreSQL lessons have keyboard and text-first routes, including a city architecture description generated from the layout, but the 3D scene and first-person walk have no nonvisual equivalent, and it points readers to ACCESSIBILITY.md for the boundary.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nikolays-pgsimcity)