jonnify·persistence /echo-persistence/postgres-wal/two-lsn-worlds

Module 11 · Dive 11.1

Two LSN worlds.

The engines chapter taught one word — LSN — as the floor's cursor: Graft's commit LSN already means three things on one change-feed. But the consistency-first ledger uses the same word for a different log over different bytes. Graft never reads Postgres's heap or its write-ahead log, so the money's durable record never reaches Tigris — it lives only in pg_data on one Fly volume. The ledger is off the floor.

Forward-tense. The gap is real today; closing it is PROPOSED, not shipped. The design is recorded and ruled (graft.pg-wal-archive.design.md, Arm A→B); this dive names the two worlds, and the next two dives close them.
One word, two logs. The top track is Graft's commit LSN — it replicates to Tigris and rides the change-feed. The bottom track is Postgres's WAL LSN — it reaches only the local volume. Tap a question to see what each LSN does, and does not, cover.
Graft · commit LSN available-first · cache + stream log → the floor Tigris · off-site /segments /logs/…/commits Postgres · WAL LSN consistency-first · the money off the floor pg_data one Fly volume local only change-feed · the one cursor commit LSN WAL LSN?
readout · Two tracks, same word. The Graft commit LSN replicates to Tigris and rides the feed; the Postgres WAL LSN reaches only pg_data on one volume — the ledger is off the floor. Tap a question.
§1

The same word, two logs

graft.pg-wal-archive.design.md

The engines chapter spent its last modules on one number. Graft's commit LSN is the available-first floor's cursor, and it already carries three meanings on one change-feed: a store-durability boundary, a replica position, and a consumer offset (Module 12–13, the one cursor). What it replicates to Tigris is the available-first tier's durable record — EchoStore's pages and the Stream Tier's trimmed slices become Graft commits behind the create-if-not-exists fence (Module 9). Postgres uses the same three letters for something else entirely. Its WAL LSN is the consistency-first ledger's write-ahead-log position — the byte offset into the log that records every change to balances and the append-only transaction ledger before it touches the heap, the log against which a committed payout must never be lost. Same word, different log over different bytes: Graft's LSN counts engine commits to Tigris; Postgres's LSN counts heap changes to its own WAL. Reading “LSN” on the feed and assuming it covers both is the mistake this module exists to prevent.

§2

Disjoint, by construction

graft.pg-wal-archive.design.md

The two logs are not merely different — they are disjoint, and disjoint by construction. Graft commits the pages it is given and replicates them to Tigris; it never reads Postgres's heap files and never reads its WAL. So when the floor's commit LSN advances and a new segment lands in the bucket, not one byte of the ledger went with it. The ledger's durable record stays where Postgres put it: in pg_data, on the single Fly volume the database runs on. That is the gap stated plainly — a host or volume loss takes the money with it, because nothing of the ledger is off-site. The available-first tier survives such a loss by reading its head back from Tigris (Module 9); the consistency-first ledger has no Tigris to read from. The floor this chapter built does not cover Postgres point-in-time recovery, and it cannot, because Graft never sees the bytes that would need recovering. The ledger is off the floor — and codemojex.postgres.md ships archive_mode = off until that is fixed, naming continuous WAL archiving and a streaming replica as the launch prerequisites: “the work before real money.”

§3

What the module proposes

forward-tense

Naming the gap sets the module's job, which is PROPOSED and forward-tense: bring the WAL LSN onto the same floor and the same cursor the available-first tier already rides. Two facts make that more than a hope. First, an archived WAL segment carries a start LSN, an end LSN, and a timeline — the end LSN is a frontier that can ride the change-feed in the exact shape the engine already publishes for its commits, so the ledger's durability becomes a platform metric beside replica position and store durability rather than a private fact of a backup tool. Second, Postgres requires its archive step to be idempotent and to refuse overwriting a same-named segment with different content — which is the create-if-not-exists conditional put Graft already uses as its commit fence (the next dive walks exactly this coincidence). Nothing here is built: the design surfaces a four-arm fork and the Operator has ruled it Arm A → Arm B — proven off-the-shelf restore for the bytes, then a read-only frontier lane for the cursor. This dive only names the two worlds; Dive 11.2 reuses the fence, and Dive 11.3 walks the ruling.

§4

References & sources