Lessons

How the engine works

37 sessions, one mechanism each. See it move, then the lab. This is the only engine course, not a second “internals” track.

Lessons = understand the machine. Interview = say it out loud. Pathways = which lesson next (including Deep Internals as an order, not a new catalog).

Start here

5 free end to end, one per major track

Every lesson

32 Pro · 33 source-grounded

Storage & row versions

FreeSource-grounded2 lab transcripts

MVCC Internals: How PostgreSQL Stores Row Versions

For ordinary non-locking SELECT/INSERT/UPDATE/DELETE, PostgreSQL readers do not block writers and writers do not block readers. Multi-Version Concurrency Control (MVCC) does that by writing a new physical tuple version on each change and deciding at read time which version each snapshot may see. Row locks, unique conflicts, and DDL still use the lock manager, MVCC is not “never wait for anything.”

Read the lesson →
🔒 ProSource-grounded1 lab transcript

Page Layout: How PostgreSQL Stores Rows on Disk

PostgreSQL storage is organized into fixed-size blocks, 8KB by default (BLCKSZ). A table (the "main fork") is an array of these blocks in one or more 1GB segment files under the database directory. Every block, heap or index, shares the same general layout, defined in src/include/storage/bufpage.h.

See what the 7 sections cover →
🔒 ProSource-grounded1 lab transcript

Snapshots and Visibility: How PostgreSQL Decides What You See

MVCC stores many versions of each row; a snapshot is the rule that selects which versions a statement or transaction may see. Conceptually it captures "which transactions had committed at the instant I started looking." The struct is SnapshotData in src/include/utils/snapshot.h, built by GetSnapshotData() in src/backend/storage/ipc/procarray.c.

See what the 10 sections cover →
🔒 ProSource-grounded3 lab transcripts

TOAST: How PostgreSQL Stores Oversized Values

A tuple must fit within a single 8KB page, PostgreSQL does not span a row across blocks. So how does a text column hold a megabyte? The answer is TOAST (The Oversized-Attribute Storage Technique), implemented in src/backend/access/common/toast_internals.c and detoast.c. When a row would be too big, TOAST compresses and/or moves large field values out of the main tuple.

See what the 8 sections cover →
🔒 ProSource-grounded1 lab transcript

HOT Updates: Same-Page Versions Without Index Writes

Because of MVCC, every UPDATE writes a new heap tuple version. A normal update also inserts a new entry in every index, even indexes on columns that did not change. HOT (Heap-Only Tuple) is the optimization that skips those index inserts when the new version fits on the same heap page and no hot-blocking index column changed. Cleanup of dead HOT versions is a separate step: opportunistic page pruning (and VACUUM), which is also where LP_REDIRECT line pointers appear.

See what the 9 sections cover →

Write-ahead log & durability

Buffers & memory

Vacuum & bloat

Query planning & execution

FreeSource-grounded2 lab transcripts

Reading EXPLAIN: How the Planner Describes a Query

The PostgreSQL executor runs a tree of plan nodes, each pulling rows from its children on demand (the Volcano/iterator model, src/backend/executor/). EXPLAIN prints that tree. The node at the top produces the final result; leaves are scans of tables or indexes. Reading a plan means reading this tree from the inside out.

Read the lesson →
🔒 ProSource-grounded1 lab transcript

How the Cost-Based Optimizer Chooses a Plan

For any non-trivial query there are many ways to get the answer, different scan methods, join orders, and join algorithms. The planner/optimizer (src/backend/optimizer/) enumerates candidate paths, estimates the cost of each, and picks the cheapest. It does not try every possibility exhaustively; it prunes aggressively.

See what the 9 sections cover →
🔒 ProSource-grounded1 lab transcript

Statistics and Selectivity: Why the Planner Guesses Wrong

The optimizer chooses plans by estimating how many rows each operation produces. Those estimates come entirely from statistics gathered by ANALYZE into the pg_statistic catalog (human-readable via pg_stats). Bad statistics → bad estimates → bad plans. Almost every "mysteriously slow query" traces back here.

See what the 9 sections cover →
🔒 ProSource-grounded1 lab transcript

Parallel Query: How PostgreSQL Splits Work Across Workers

Historically each PostgreSQL query ran in a single backend process. Parallel query lets the planner split eligible work across multiple worker processes that execute parts of the plan concurrently, then combine results. The machinery lives in src/backend/executor/nodeGather.c, execParallel.c, and the parallel-aware scan nodes.

See what the 9 sections cover →
🔒 ProSource-grounded1 lab transcript

Bitmap Scans: How PostgreSQL Combines Indexes

A plain index scan is great for high selectivity (few rows) and a sequential scan is great for low selectivity (most rows). In between, say 1-15% of a table, both are suboptimal: the index scan jumps around the heap in random order, while the seq scan reads far too much. The bitmap scan fills this gap and is implemented in src/backend/executor/nodeBitmapHeapScan.c and the bitmap index scan nodes.

See what the 8 sections cover →
🔒 ProSource-grounded1 lab transcript

Partitioning: How Declarative Partitioning Prunes Work

A partitioned table is one logical table split into many physical child tables by a partition key. The win is not magic speed on every query, it is the ability to skip entire partitions (pruning), to drop old data instantly (DROP/DETACH a partition instead of a massive DELETE), and to vacuum and index partitions independently. Declarative partitioning lives in src/backend/partitioning/.

See what the 8 sections cover →
🔒 ProSource-grounded2 lab transcripts

Caching Plans: Prepared Statements and the Generic Plan

Every SQL statement goes through parse → analyze → rewrite → plan → execute. For repeated queries that differ only in parameter values, redoing parse and plan each time is wasted work. Prepared statements cache the parsed and (sometimes) planned form so subsequent executions skip that overhead. The logic lives in src/backend/utils/cache/plancache.c.

See what the 8 sections cover →
🔒 ProSource-grounded

Query Executor: From Plan Tree to Tuples

After the planner chooses a Plan tree, the executor builds a parallel PlanState tree, initializes nodes (ExecInitNode), and pulls tuples by calling each node's ExecProcNode method, usually starting at ExecProcNodeFirst. EXPLAIN ANALYZE times that pull loop. This lesson is the missing link between “the plan looks right” and “what the backend actually runs.”

See what the 9 sections cover →

Indexes

Concurrency & locking

Connections & pooling

Replication & HA

🔒 ProSource-grounded1 lab transcript

Streaming Replication: walsender and walreceiver

Streaming replication keeps a standby byte-for-byte identical to its primary by shipping the primary's WAL stream and replaying it continuously. Because it replays the same physical changes, the standby is an exact copy, same data files, same block contents, which is why it requires the same major version and architecture.

See what the 8 sections cover →
🔒 ProSource-grounded

Logical Replication and Logical Decoding

Where physical replication ships raw WAL blocks, logical replication ships logical row changes, "insert this row", "update that row", reconstructed from the WAL by logical decoding. Because it operates at the row level via SQL, publisher and subscriber can differ in major version, architecture, and even schema, and you can replicate a subset of tables. This flexibility powers upgrades, selective data distribution, and integration pipelines.

See what the 9 sections cover →
🔒 ProSource-grounded

Replication Slots: Guaranteeing WAL Retention

A replica (physical standby or logical subscriber) consumes WAL from the primary. If the primary recycles WAL before the replica has read it, the replica falls irrecoverably behind and must be rebuilt. The old wal_keep_size approach, keep a fixed amount of WAL and hope it's enough, is fragile. Replication slots solve this precisely by tracking exactly how far each consumer has progressed and retaining WAL until then.

See what the 6 sections cover →
🔒 ProSource-grounded1 lab transcript

Synchronous Replication and Quorum Commit

By default PostgreSQL replication is asynchronous: a primary commits once its own WAL is durable, without waiting for any standby. If the primary then fails before a standby received the latest WAL, those last transactions are lost. Synchronous replication makes the primary wait for standby confirmation before reporting commit success, eliminating that data-loss window, at the cost of commit latency.

See what the 4 sections cover →
🔒 ProSource-grounded1 lab transcript

Hot Standby and Recovery Conflicts

Hot standby lets a streaming standby serve read-only queries while it continuously replays WAL from the primary. This is how PostgreSQL scales reads: route SELECT traffic to one or more standbys. But it creates a tension that does not exist on the primary, the standby is doing two things at once: replaying changes and answering queries against the data those changes are modifying.

See what the 6 sections cover →
🔒 ProSource-grounded

pg_rewind: Reusing a Diverged Old Primary

pg_rewind is a frontend utility (src/bin/pg_rewind), not backend postmaster code: it reuses an old primary’s data directory by copying blocks that diverged after the timeline fork, using the old primary’s WAL as the map. Still source-grounded, just not inside the server process.

See what the 7 sections cover →

Schema changes & migrations (engine locks + patterns)

Schema changes & migrations (ops pattern)

Connections & pooling (HA routing, ops)

HA orchestration (not engine source)