NEDB Docs / Reference / Architecture

One principle, three generations: state is a pure function of a sealed log. Everything else — time travel, provenance, proofs — falls out of that sentence.

The pipeline

            ┌──────────────────────────────────────────────────────────┐
  put/del → │  OpLog  (BLAKE2b hash chain · per-client nonce ·          │ ← single source of truth
  link      │          idempotency keys · causal provenance fields)     │
            └───────────────┬──────────────────────────────────────────┘
            deterministic fold │ (state = pure function of the log)
     ┌──────────────┬──────────┴──────┬───────────────┬────────────────┐
     ▼              ▼                 ▼               ▼                ▼
MVCC store     Relations          Indexes         CauseMap          BlobStore
(time-travel)  (graph+AS OF)      eq/ord/search   (reverse index)   (Cascade CDC)

                     ┌─────────────────────────────────┐
  Thread-safe →      │  Sequencer (group-commit)         │ ← single writer, parallel readers
                     │  — one committer thread/db        │
                     │  — batch fsync                    │
                     └─────────────────────────────────┘

The provenance machinery is load-bearing, not metadata stapled on: CauseMap is a reverse index over causal edges (that is why TRACE … REVERSE is as fast as forward), and the Relations layer backs both TRAVERSE and the AS OF joins. The daemon is a single-writer group-commit sequencer — parallel reads, batched durable writes, one hash chain per database, zero write-write races.

Three storage generations

GenLayoutTrade
v1 · AOFappend-only log, replay on opensimple, universal fallback; O(n) restart
v2 · DAGcontent-addressed loose objects, one file per version, MANIFEST for O(1) warm starttrivially atomic writes; file-metadata churn at scale (~185 writes/s ceiling on busy disks)
v3 · segmentsappend-only packs, one fsync per batch, .idx sidecars, compactioncost tracks bytes not object count; opt-in, dual-read compatible with v2

Same API across all three — a v1 store auto-migrates to the DAG on first --dag startup, and v2 stores open in v3 mode without a rewrite. Cold starts accept connections immediately (reads serve from the DAG; writes return 503 until the scan gate flips, progress streams over /events); every restart after the first is O(1) from the MANIFEST.

Encryption

AES-256-GCM at rest with a TMK/DEK double-envelope: a 32-byte hex master key (NEDB_TMK) wraps per-database data keys. Key handling fails closed — a malformed provided key is an error, never a silent fall-through to plaintext. Because a node's hash is a function of its ciphertext, state-root leaves commit to logical content rather than object hashes (see Provenance).

Repo layout

python/nedb/        reference engine (pure Python — always-works baseline)
rust/
  nedb-v2/          v2/v3 DAG engine (tokio + axum + BLAKE2b) — the core everything binds
  nesql-cli/        the nesql CLI
  nedb-core/        v1 Rust engine
  nedb-py/          maturin PyO3 binding → PyPI native wheels
  nedb-node/        napi-rs binding → npm native addons
  nedb-wrap/        the wrap_* surface at native speed
vendor/postgresql/  PostgreSQL 17.4 grammar, vendored (gram.y, kwlist.h, …)
distributions/      crypto-database + aof-db submodules (tri-distribution)
bench/              benchmarks.py + RESULTS.md — the dated numbers
vectors/            state_root_v1.json — cross-engine test vectors
tests/              engine + concurrent + causal + bitemporal + deploy + perf suites