wal-db 1.0.0

Write-ahead log primitive for Rust storage engines. Durable, recoverable, lock-free append path. The WAL substrate under lsm-db, txn-db, raft-io, and Hive DB.
Documentation
# wal-db v1.0.0 — Stable

**The first stable release.** wal-db is a write-ahead log primitive for Rust
storage engines: the durable, append-only substrate a database writes to before it
acknowledges anything. With 1.0 the public API is frozen until 2.0 and the on-disk
format is frozen for the 1.x line — a log written by any 1.x release reads back on
any other.

There are no functional changes since 0.9.1. 1.0.0 is the commitment to a surface
that has been built, measured, and hardened across the 0.x series.

## What wal-db gives you

A WAL is the workhorse no database avoids: every state change is appended to a
durable log *before* it is acknowledged, and that log rebuilds state after a
crash. Most Rust databases bury their WAL inside the engine; wal-db publishes it as
a clean, composable primitive so an LSM tree, a B-tree store, a transaction
manager, and a Raft log can all share one well-tested implementation.

- **Lock-free multi-writer append.** Many threads append at once with no global
  lock. Each append reserves its byte range with a single atomic step, and that
  range's start offset *is* the record's LSN — so reservations never overlap or
  reorder, and seeking to an LSN is O(1).
- **Explicit, two-step durability.** `append` returns when the record is in the OS
  page cache; `sync` returns when it is on stable storage. The two are never
  conflated — the single most common way to lose data with a WAL.
- **Group commit.** Concurrent `sync` calls coalesce into one fsync, so the cost of
  durability is amortised across everyone committing together.
- **Platform-correct flush.** `fdatasync` on Linux, `FlushFileBuffers` on Windows,
  and `fcntl(F_FULLFSYNC)` on macOS — not plain `fsync`, which leaves data in the
  drive's write cache.
- **Torn-write detection and self-healing recovery.** A CRC32C checksum per record;
  on open, recovery stops at the first incomplete or corrupt record and truncates
  that torn tail. A corrupt length can never drive a wild allocation.
- **Recovery policies.** Stop at the first damaged record, or skip past it for
  forensic partial recovery.
- **Segment rotation.** Optionally stripe the log across bounded segment files for
  bounded recovery and archival, with records spanning boundaries freely.
- **Compaction, both ends.** `iter_from` replays from any LSN; `truncate_after`
  drops a tail (a Raft conflict), and `truncate_before` reclaims a prefix (a
  checkpoint), durably and crash-safely.
- **Optional typed records.** Serialise any value via `pack-io` behind a feature;
  the byte-record API is unchanged when it is off.
- **Pluggable backend.** File-backed by default, with a `WalStore` trait for custom
  and in-memory stores.

## The common case is four calls

```rust
use wal_db::Wal;

# fn apply(_lsn: wal_db::Lsn, _bytes: &[u8]) {}
# fn main() -> Result<(), wal_db::WalError> {
# let dir = tempfile::tempdir().map_err(wal_db::WalError::from)?;
# let path = dir.path().join("app.wal");
let wal = Wal::open(&path)?;          // open (recovers any torn tail)
let _lsn = wal.append(b"a change")?;  // append (into the page cache)
wal.sync()?;                          // sync (the durability barrier)

for entry in wal.iter()? {            // iter (replay on restart)
    let entry = entry?;
    apply(entry.lsn(), entry.data());
}
# Ok(())
# }
```

## Stability guarantees

- **API frozen until 2.0.** Every public item is stable. `WalError` and
  `RecoveryPolicy` are `#[non_exhaustive]` and `WalConfig` is a builder, so the
  surface can still grow additively within the 1.x line without a breaking change.
- **On-disk format frozen for 1.x.** The record framing (frozen since 0.3.0) and
  the segment layout (since 0.3.1) will not change in a backward-incompatible way
  within 1.x. The normative specification is [`docs/ON_DISK_FORMAT.md`]../ON_DISK_FORMAT.md.
- **MSRV 1.85**, Rust 2024 edition. Cross-platform: Linux, macOS, Windows.

## How it was hardened

- **Fuzzing** — a continuous `cargo-fuzz` recovery harness; recovery never panics
  or over-allocates on arbitrary bytes across millions of inputs.
- **Model checking** — loom verifies the lock-free append and group-commit paths
  under exhaustive interleavings.
- **Adversarial and fault-injection tests** — hostile recovery inputs (garbage
  prefixes, implausible lengths, corrupt and torn markers) and injected I/O
  failures (disk-full, fsync failure) through the `WalStore` seam.
- **Property tests** — prefix compaction across random record sets, segment sizes,
  and truncation points, reopened and checked for completeness.
- **Benchmarked honestly** — against a hand-rolled inline WAL; numbers and method
  in [`docs/BENCHMARKS.md`]../BENCHMARKS.md.

The full suite is green on Windows and Linux, on stable and MSRV 1.85, with macOS
covered by the CI matrix.

## Performance, in one line

The LSN reservation is a single ~4 ns atomic; a file append is syscall-bound (the
`pwrite` the durability contract requires); and group commit beats a hand-rolled
inline WAL by ~1.9× for concurrent durable commits, widening with more writers and
faster storage. Details in [`docs/BENCHMARKS.md`](../BENCHMARKS.md).

## Upgrading from 0.9.x

Nothing to do. There are no API or on-disk changes from 0.9.1; 1.0.0 only freezes
the surface.

## Installation

```toml
[dependencies]
wal-db = "1.0"

# Typed records:
wal-db = { version = "1.0", features = ["pack-io"] }
```

MSRV: Rust 1.85.

## Documentation

- [README]https://github.com/jamesgober/wal-db/blob/main/README.md
- [API Reference]https://github.com/jamesgober/wal-db/blob/main/docs/API.md
- [On-Disk Format]https://github.com/jamesgober/wal-db/blob/main/docs/ON_DISK_FORMAT.md
- [Benchmarks]https://github.com/jamesgober/wal-db/blob/main/docs/BENCHMARKS.md
- [CHANGELOG]https://github.com/jamesgober/wal-db/blob/main/CHANGELOG.md

---

**Full diff:** [`v0.9.1...v1.0.0`](https://github.com/jamesgober/wal-db/compare/v0.9.1...v1.0.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/wal-db/blob/main/CHANGELOG.md#100---2026-06-05).