CONCEPT Cited by 1 source
Unlogged table (Postgres)¶
Definition¶
An unlogged table in Postgres is a table declared with CREATE
UNLOGGED TABLE … whose writes bypass the write-ahead log (WAL)
entirely. No WAL records are generated, no fsync happens at commit
for the data blocks, and the table is truncated on any non-clean
shutdown or crash recovery. Inserts are faster because Postgres is
not making durability guarantees about the data.
The two consequences that matter for system design¶
-
No crash recovery. A crashed server loses all rows in unlogged tables. Intended for workloads where the data is cheaply reconstructible or strictly ephemeral (scratch computation, session caches, frame buffers, idempotent derived tables).
-
No logical replication. Logical replication reads from the WAL. If a table's writes don't land in the WAL, they are invisible to every replication slot. The only way to consume changes from an unlogged table is polling:
SELECT … WHERE seq > $1in a loop, or a periodic snapshot diff. This breaks the logical-replication-as- pub/sub pattern entirely. (Source: sources/2026-02-27-planetscale-video-conferencing-with-postgres.)
When unlogged tables make sense¶
- High-throughput scratch data you are happy to lose on crash (in-memory-cache-backed by durable source).
- Build / ETL intermediate tables that will be rebuilt from source if lost.
- Session state when the application accepts losing all sessions on a restart.
When they don't¶
- You need logical replication / CDC. Every row change must land in the WAL to be visible to subscribers. Unlogged + replication is a contradiction.
- You can't tolerate the truncation-on-crash blast radius. On crash, all rows in unlogged tables across the database are truncated. If one of them held partial state that other tables referenced, you have a referential-integrity incident.
- You want simple ephemeral deletion of old rows. See
TTL-based row deletion — a
cron
DELETEwith an interval predicate is a cleaner way to bound an otherwise-normal logged table.
Seen in¶
- sources/2026-02-27-planetscale-video-conferencing-with-postgres
— canonical wiki framing of the replication trade-off. Nick Van
Wiggeren evaluates unlogged tables as a candidate for his Postgres
video-chat hack and rejects them specifically because of the
replication gap: "Unlogged tables go the other direction. Instead
of changing how we get data out of Postgres, they change how data
goes in. Unlogged tables skip the WAL entirely — no write-ahead
logging, no fsync, no crash recovery. Inserts are faster because
Postgres isn't making durability guarantees about video frames. I
didn't like that because logical replication reads from the WAL.
If the table doesn't write to the WAL, it doesn't appear in the
replication stream. To make this work, we'd have to fall back to
polling —
SELECT * FROM video_frames WHERE seq > $1in a loop. This might have worked fine, maybe better — but something about rendering video from a polling loop ofSELECT *didn't feel good." The canonical mechanism statement is unlogged writes skip the WAL, and the WAL is the logical-replication stream, so unlogged tables are invisible to every subscriber.