Open-Source Wikis

/

etcd

/

Systems

/

Write-ahead log (WAL)

etcd-io/etcd

Write-ahead log (WAL)

Source: server/storage/wal/.

Purpose

The WAL is the durable log of every Raft entry, hard state, and CRC checkpoint. It is what makes etcd survive crashes: until an entry is fsynced into the WAL, the leader will not acknowledge it as committed. The WAL is also the first thing a member reads on startup to reconstruct its Raft state.

Directory layout

server/storage/wal/
├── wal.go              # WAL struct, ReadAll, Save, releaseLockTo
├── encoder.go, decoder.go
├── repair.go           # truncates partial last record
├── version.go          # min-server / cluster compatibility
├── metrics.go
├── file_pipeline.go    # pre-allocates next WAL segment
├── walpb/              # WAL record protobuf (Type, CRC, Data)
└── testing/, testdata/

File format

A WAL is a sequence of fixed-name segment files (0000000000000000-0000000000000000.wal, ...) in the <data-dir>/member/wal/ directory. Each file is a stream of walpb.Record entries:

[ length | CRC | Type | Data ]

Record types include:

Type Carried payload
metadataType Cluster metadata (CIDr, member ID)
entryType Raft log entry
stateType Raft HardState
crcType CRC checkpoint at start of file
snapshotType Pointer to a snapshot (term/index)

Segments are opened in append-only mode with a 64 MB pre-allocation (file_pipeline.go). When a segment fills up, the pipeline rotates to the next one already on disk.

Key abstractions

Symbol File Description
WAL server/storage/wal/wal.go Open log; offers Save, SaveSnapshot, ReadAll, Close
Encoder / Decoder server/storage/wal/encoder.go, decoder.go Length-prefixed CRC-checked stream codec
filePipeline server/storage/wal/file_pipeline.go Background pre-allocation of next segment
Repair server/storage/wal/repair.go Trims a truncated last record on startup
walpb.Record server/storage/wal/walpb/record.proto The on-disk record type

How it works

graph LR
    raft[raftNode] -->|Save(hardState, entries)| wal[WAL]
    wal --> enc[Encoder]
    enc --> file[(WAL segment file)]
    file -->|fsync| disk[(disk)]
    wal --> pipe[filePipeline]
    pipe --> nextfile[(next segment)]
    raftRestart[startup] -->|ReadAll| wal
    wal --> dec[Decoder]
    dec --> file
  • Save: the WAL appends one record per entry plus a record for the new hard state, computes the CRC into the running CRC accumulator, and Sync()s the file. Segment rotation is automatic.
  • ReadAll: on startup, replays records into the in-memory list of Raft entries plus the latest hard state. Truncated trailing records get repaired by repair.go.
  • Snapshot: when a snapshot is created, the WAL records a pointer to it; subsequent log files can be released up to that pointer.

Integration points

  • Consumed by server/etcdserver/raft.go's Ready loop.
  • Snapshot pointer file format is shared with server/etcdserver/api/snap/.
  • server/storage/storage.go exposes a unified Storage facade that bundles WAL + snap + bolt.
  • etcdutl and tools/etcd-dump-logs/ parse the same format for forensics.

Entry points for modification

  • New record type → add to walpb/record.proto, run scripts/genproto.sh, add an Encoder/Decoder branch.
  • File-format version bumps → version.go and the migration framework in server/storage/schema/migration.go.
  • Performance: file_pipeline.go is the place to tweak pre-allocation strategy; the project has resisted larger segments to keep recovery fast.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Write-ahead log (WAL) – etcd wiki | Factory