Skip to content

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

  1. 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).

  2. 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 > $1 in 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 DELETE with an interval predicate is a cleaner way to bound an otherwise-normal logged table.

Seen in

  • sources/2026-02-27-planetscale-video-conferencing-with-postgrescanonical 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 > $1 in a loop. This might have worked fine, maybe better — but something about rendering video from a polling loop of SELECT * 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.
Last updated · 550 distilled / 1,221 read