PostgreSQL Write-Ahead Logging (WAL): Crash Recovery and Replication Internals

Jun 17, 2026 · 12 min read

Learn how PostgreSQL Write-Ahead Logging works, why it exists, and how it enables crash recovery, durability, and replication.

PostgreSQL Write-Ahead Logging (WAL): Crash Recovery and Replication Internals

Every durable database eventually faces the same question: what happens if the server crashes in the middle of a write? PostgreSQL solves this problem using Write-Ahead Logging (WAL). It’s one of the most important pieces of the database because it guarantees durability, powers crash recovery, and serves as the foundation for replication.

The Problem WAL Solves

Imagine updating a user’s balance.

UPDATE accounts
SET balance = balance - 100
WHERE id = 1;

At first glance, this seems straightforward. PostgreSQL modifies the row and stores the change on disk.

The problem appears when a crash occurs during the write process.

A database page is usually much larger than a single row. PostgreSQL modifies pages in memory and eventually flushes them to disk. If power is lost while a page is being written, the database can be left in an inconsistent state.

Without some form of recovery mechanism, partially written changes could corrupt data.

A database must be able to recover committed transactions even if it crashes immediately afterward.

Instead of writing data pages first, PostgreSQL writes a description of the change into WAL.

Only after the WAL record is safely stored can the transaction be considered committed.

WAL Motivation and Crash Scenario

This simple idea is the foundation of PostgreSQL durability.

Understanding Write-Ahead Logging

The rule behind WAL is surprisingly simple:

Changes must be written to the WAL before the corresponding data page reaches disk.

That’s why it’s called Write-Ahead Logging.

When a transaction modifies data, PostgreSQL generates WAL records describing what changed.

A simplified flow looks like this:

  1. Transaction modifies a row
  2. Data page changes in shared buffers
  3. WAL record is generated
  4. WAL record is flushed to disk
  5. Transaction commits
  6. Data page is written later

The actual table data does not need to reach disk immediately.

Instead, PostgreSQL only guarantees that the WAL has been persisted.

This significantly improves performance because sequential WAL writes are much cheaper than random page writes.

WAL Write Path

Internally, WAL files are stored inside:

pg_wal/

You can inspect the current WAL location using:

SELECT pg_current_wal_lsn();

The returned value is an LSN (Log Sequence Number), which represents a position within the WAL stream.

WAL and Crash Recovery

Crash recovery is where WAL becomes truly powerful.

Suppose a transaction commits successfully.

BEGIN;

UPDATE products
SET stock = stock - 1
WHERE id = 10;

COMMIT;

The WAL record reaches disk.

The actual table page does not.

A few milliseconds later the server crashes.

Without WAL, that committed transaction would be lost.

With WAL, PostgreSQL performs recovery during startup.

It reads WAL records from the last checkpoint and replays every committed change that was not yet written into data files.

This process is commonly called REDO.

During startup PostgreSQL:

  • Reads the latest checkpoint
  • Locates WAL records after that checkpoint
  • Replays modifications
  • Restores a consistent state

Crash Recovery Using WAL Replay

Because committed transactions exist inside WAL, PostgreSQL can reconstruct the database even when table pages were never flushed before the crash.

WAL, Checkpoints, and Performance

If PostgreSQL can replay WAL records, why write data pages at all?

Eventually WAL replay would become too expensive.

That’s where checkpoints come in.

A checkpoint forces dirty pages from memory to disk and records a checkpoint location in WAL.

During crash recovery PostgreSQL only needs to replay WAL generated after the latest checkpoint.

You can inspect checkpoint activity:

SELECT *
FROM pg_stat_bgwriter;

Checkpoint frequency is controlled by settings such as:

checkpoint_timeout = 5min
max_wal_size = 1GB

There’s a tradeoff here.

Frequent checkpoints:

  • Faster recovery
  • More disk writes
  • Higher I/O pressure

Less frequent checkpoints:

  • Better runtime performance
  • Longer crash recovery

Checkpoints reduce recovery work, while WAL preserves committed changes between checkpoints.

WAL and Checkpoint Relationship

Understanding this balance is important when tuning PostgreSQL for production workloads.

WAL as the Foundation of Replication

Before learning WAL internals, I assumed replication worked by copying table data between servers.

PostgreSQL does something smarter.

The primary server continuously generates WAL records.

Replica servers receive those records and replay them.

As WAL is applied, replicas reproduce exactly the same changes occurring on the primary.

The flow looks like:

Primary Database

 WAL Stream

 Standby Replica

 WAL Replay

 Consistent Copy

This is known as physical replication.

Because replicas replay WAL rather than executing SQL statements, replication remains efficient even for large workloads.

Useful monitoring query:

SELECT *
FROM pg_stat_replication;

This view shows connected replicas and replication lag.

WAL Based Replication Flow

Once I understood that replication is essentially WAL shipping plus replay, many PostgreSQL replication concepts became much easier to understand.

Important WAL Concepts

Several PostgreSQL internals become easier to understand once WAL enters the picture.

LSN (Log Sequence Number)

Every WAL record receives an LSN.

Examples:

0/16B6A70
0/1704C58
0/1704F18

LSNs help PostgreSQL track:

  • Replication progress
  • Recovery progress
  • Backup consistency
  • WAL replay position

WAL Segments

WAL is stored as segment files inside:

pg_wal/

Common filenames look like:

000000010000000000000001

PostgreSQL rotates through these files as new WAL records are generated.

WAL Archiving

Production systems often archive WAL files.

This allows:

  • Point-in-time recovery (PITR)
  • Disaster recovery
  • Backup restoration

The combination of base backups and archived WAL enables recovery to an exact moment in time.

Final Thoughts

WAL is much more than a transaction log. It is the mechanism that allows PostgreSQL to provide durability, recover from crashes, and replicate data across servers.

The key idea is simple: write the description of a change before writing the actual data page. From that single principle PostgreSQL gains reliable crash recovery, efficient disk writes, replication, backups, and point-in-time recovery.

As I continue learning PostgreSQL internals, WAL feels like one of those topics that connects many other concepts together. Checkpoints, replication, backups, recovery, and durability all make more sense once you understand the WAL stream sitting underneath them.

PostgreSQL Database Internals WAL Replication
Available for opportunities

Need someone who enjoys solving hard engineering problems?

I enjoy building reliable systems, understanding complex architectures, and solving challenging engineering problems. If you're looking to hire a software engineer who combines curiosity, ownership, and strong technical fundamentals, I'd love to hear from you.

deploy-status

> Status: Available

> Curiosity: HIGH

> Auto Scaling: Enabled