Check the v0.2 graph update: broader Cypher path coverage, multi-segment `shortestPath` and `allShortestPaths`, named paths across multiple variable-length segments, stronger undirected fast paths, runtime-observed graph `EXPLAIN`, Neo4j-oriented compatibility evidence, and a current benchmark snapshot vs Neo4j, SurrealDB, and pgstack. Read the full v0.2 breakdown.

WAL Contract

The Write-Ahead Log is the durability anchor of AionDB. This page documents the v0.2 frozen contract: segment framing, record kinds, recovery rules. The authoritative source is the code:

If a value in this page disagrees with the code, the code wins.

Segment files

WAL segments live under <data-dir>/wal/. Segment filenames are zero-padded numerics, e.g. wal_000000000001.log. Segments are appended sequentially. Once a segment is full, a new one is created with the next id.

Segment header

The current segment header layout (format version 3):

OffsetSizeFieldNotes
08magicb"AIONWAL1"
81format_version3 for the v0.2 line.
91lsn_mode1 logical (counter), 2 byte-offset.
108system_idCluster identity hash.
184timelineReplication timeline id.

Older headers (v1 9 bytes, v2 10 bytes) are accepted on read for one major release window. New segments always carry the current 22-byte header. The legacy b"AIONWAL\0" magic is also accepted on read.

LSN modes

ModeBehavior
LogicalLSN increments by 1 per record. Easiest to read in tests.
ByteOffsetLSN increments by the encoded record length. Default. Matches PostgreSQL semantics and gives a free byte-position invariant.

The mode is fixed at segment creation. Changing the LSN mode requires a full upgrade.

Records

A WAL record is a fixed-tag header plus a tag-specific payload. The v0.2 release line freezes 86 record kinds, tagged 0..=85.

The full mapping is in crates/aiondb-wal/src/record.rs:

Frozen tag table

TagVariant
0BeginTxn
1CommitTxn
2AbortTxn
3InsertRow
4DeleteRow
5UpdateRow
6CreateTable
7DropTable
8CreateIndex
9DropIndex
10AlterTable
11Checkpoint
12UpdateStatistics
13–29Catalog DDL (CatalogCreateSchemaCatalogSetTableDescriptor)
30–32Adjacency index (RegisterEdgeTable, AdjacencyInsert, AdjacencyRemove)
33–43Catalog DDL (CatalogDropTableCatalogSetSequenceValue)
44–49Page-level redo (FullPageImage, PagedRowRef, FullPageImageBatch, PagePatch, PagePatchBatch, PageSetU64Batch)
50–67B-tree redo (DiskBtreeMetaUpdateDiskBtreeInternalCollapseChain)
68–70Autocommit row ops (AutocommitInsertRow, AutocommitDeleteRow, AutocommitUpdateRow)
71–76User-defined types (CatalogCreateDomainCatalogAlterUserType)
77–78Casts (CatalogCreateCast, CatalogDropCast)
79–81Row-level policies (CatalogCreatePolicyCatalogAlterPolicy)
82–83Rules (CatalogCreateRule, CatalogDropRule)
84–85Comments (CatalogSetComment, CatalogDropComment)

This table is asserted by frozen_wal_tag_table_is_dense_and_unique and frozen_wal_tag_table_matches_record_tag in record.rs. Reordering, renumbering, or removing a tag inside the v0.2 line is a breaking change and is forbidden by these tests.

Tag stability rules

Within the v0.2 line:

A future major version may rewrite the table; this page documents only v0.2.

Record framing

Inside a segment, records are written one after another. Each record carries:

FieldSizeNotes
payload_length4Length of the record payload (little-endian u32).
entry_lsn8LSN assigned to this record (little-endian u64).
prev_lsn8Backward link to the previous record's LSN, 0 if start of stream.
database_id4Database id owning this record.
tag1Record kind, one of the frozen tags above.
payloadNTag-specific payload, encoded per codec.rs.
checksum4CRC32C of the preceding bytes.

A record whose length, prev-link, or checksum does not validate is treated as the tail of the segment. Recovery stops there for that segment.

LSN semantics

The LSN is a monotonic, never-reused position in the WAL stream. Two guarantees apply:

  1. Every committed record has a strictly increasing LSN.
  2. The LSN of the next record is determined by the LSN mode at segment creation time.

LSN 0 is reserved to mean "no record" and never appears as an actual entry LSN.

Idempotent recovery

The v0.2 recovery contract is:

Reading the same WAL state twice from the same start LSN produces the same entry sequence, byte for byte.

A replayer that crashes part-way through recovery can restart and rely on this. The recovery procedure must:

This contract is asserted by reader_replay_is_idempotent_within_a_single_run and reader_replay_is_idempotent_across_reopen in reader.rs.

Checkpoints

A Checkpoint record (tag 11) marks an LSN at which the database state can be reconstructed without replaying earlier records. Two derived rules:

CommitTxn, AutocommitInsertRow, AutocommitDeleteRow, and AutocommitUpdateRow are the only record kinds that publish a durable transaction effect on their own. Every other record kind is part of a transaction and is only durable when paired with the matching CommitTxn.

Group commit

Multiple concurrent commits can batch into a single fsync. The batching delay is group_commit_delay_micros (default 1000 µs). Group commit does not change the LSN order or the on-disk format; it only changes how many fsync calls are issued per second.

Compression

WAL records may be compressed per-record with lz4 or zstd when WalCompression is not None. The framing is unchanged: only the payload bytes between header and checksum are compressed. The compression mode is recorded in the per-entry header bits.

Archive and authentication

If AIONDB_WAL_ARCHIVE_DIR is set, every closed segment is copied there before recycling. If AIONDB_WAL_ARCHIVE_HMAC_KEY is set, archived segments carry an .hmac sidecar so corruption-during-transit is detected on restore. Local-only HMAC for hot WAL is enabled with AIONDB_WAL_LOCAL_HMAC_KEY.

These are infrastructure-level concerns; the record format above is unchanged when HMAC is enabled.

What is not part of the v0.2 contract

Pointers