Skip to content

Durability: Crash-Safe Writes & Atomic Operations โ€‹

FLASH DB ensures data durability through configurable WAL fsync and atomic SSTable operations.

Architecture โ€‹

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                     Memory (MemTable)                     โ”‚
โ”‚                   Read + Write Cache                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                      โ”‚ flush()
                      โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              Persistent Storage (SSTable)                 โ”‚
โ”‚           Write-Ahead Log (WAL) + Sorted Run              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

WAL (Write-Ahead Log) โ€‹

Every mutation goes through the WAL before hitting memory:

Client Request โ†’ WAL Frame(s) โ†’ fsync (mode-dependent) โ†’ MemTable Update โ†’ Response

Durability Modes (v1.2.5+) โ€‹

ModeBehaviorDefault
strictfsync after every frameโ€”
balancedBatch fsync every 64 ops or 25 ms; full sync on close()โœ…
throughputNo auto-fsync until close()โ€”
js
import { FlashClient } from "flash-zk";

const client = new FlashClient({
  storagePath: "./flash_data",
  engineOptions: { durability: "strict" }, // max safety
});

// Low-level WAL
import { FlashArc } from "flash-zk/engine/arc.mjs";
const wal = new FlashArc("./data/commit.farc", { durability: "balanced" });

See Engine Options for full tuning.

Crash Recovery โ€‹

On startup, WAL records are replayed to restore in-memory state:

  1. WAL file is read sequentially
  2. Each frame is deserialized (opcode + key + data)
  3. MemTable is reconstructed from valid frames
  4. Corrupt or truncated frames are skipped with a warning
js
// WAL recovery is automatic on collection.init()
await collection.init();

Atomic SSTable Writes โ€‹

SSTables are written atomically using a temp-file โ†’ rename pattern:

1. Write to .tmp file
2. fsync the .tmp file (ensure data on disk)
3. fsync the parent directory (ensure rename is durable)
4. Rename .tmp โ†’ final name
5. fsync parent directory again

This guarantees that either:

  • The complete SSTable exists after a crash, or
  • The old SSTable is intact (no partial writes)

Durability Guarantees โ€‹

ScenarioData Safe?Recovery
Crash after WAL fsync / close()โœ… YesWAL replay
Crash during SSTable flushโœ… YesAtomic rename
Crash during WAL append (balanced)โš ๏ธ Last batch may replayWAL replay
Crash in throughput mode before closeโš ๏ธ Unsynced frames lostPartial replay
Power loss mid-write (strict mode)โœ… Yesfsync ensures disk write

Performance Tuning โ€‹

js
// Bulk import โ€” call close() to flush
engineOptions: {
  durability: "throughput";
}

// Production default
engineOptions: {
  durability: "balanced";
}

WARNING

throughput mode may lose recent WAL frames on crash. Use only for disposable data or when you explicitly call close() before shutdown.

Zero-knowledge encrypted intelligence ยท Apache 2.0