NEDB — a versioned, self-compressing, time-traveling embedded database (replay-protected, idempotent, relational, searchable) with durable AOF persistence and a server daemon (nedbd).
Project description
NEDB
Hash-chained · time-traveling · bi-temporal · causally-provable embedded database.
Replay-protected · idempotent · relational · filterable · sortable · searchable · concurrent. One Rust core → ships to PyPI and npm from a single source.
What makes NEDB different
Every database stores what. NEDB stores what, when, when it was true, and why — all sealed in a cryptographic hash chain that proves none of it was tampered with.
| Capability | NEDB | SQLite | Redis | MongoDB |
|---|---|---|---|---|
| Hash-chained tamper evidence | ✅ | ❌ | ❌ | ❌ |
Time-travel reads (AS OF seq) |
✅ | ❌ | ❌ | ❌ |
Bi-temporal (VALID AS OF date) |
✅ | ❌ | ❌ | ❌ |
| Causal Write Provenance | ✅ | ❌ | ❌ | ❌ |
| Replay-protected idempotent writes | ✅ | ❌ | ❌ | ❌ |
| SQL + Redis + MongoDB adapters | ✅ | — | — | — |
| Concurrent group-commit daemon | ✅ | ❌ | ✅ | ✅ |
| At-rest AES-256-GCM encryption | ✅ | ❌ | ❌ | — |
Install
pip install nedb-engine # Python ≥ 3.8 — pure-Python + optional Rust native wheel
npm install nedb-engine # Node ≥ 16 — napi-rs prebuilt binaries
Python — 5-minute tour
from nedb import NEDB
db = NEDB("./mydata") # durable: every op is AOF-logged, fsync'd, and hash-chained
# db = NEDB() # or in-memory
db.create_index("users", "status", "eq")
db.create_index("users", "bio", "search")
db.put("users", "alice", {"name": "Alice", "age": 31, "status": "active", "bio": "rust hacker"})
db.put("users", "bob", {"name": "Bob", "age": 24, "status": "active", "bio": "python dev"})
# NQL: WHERE + ORDER BY + LIMIT + SEARCH + TRAVERSE + GROUP BY
db.query('FROM users WHERE status = "active" ORDER BY age ASC')
db.query('FROM users SEARCH "rust"')
db.query('FROM users GROUP BY status COUNT')
# Time-travel — AS OF any past sequence
snap = db.seq
db.put("users", "alice", {"name": "Alice", "age": 32, "status": "retired"})
db.get("users", "alice", as_of=snap) # → age 31, status active
# Bi-temporal — VALID AS OF any past date
db.put("policy", "rate_2024", {"pct": 5.0}, valid_from="2024-01-01", valid_to="2024-12-31")
db.put("policy", "rate_2025", {"pct": 6.0}, valid_from="2025-01-01")
db.query('FROM policy VALID AS OF "2024-06-15"') # → rate 5.0
# Causal Write Provenance — why did this write happen?
db.put("inputs", "msg_1", {"text": "user prefers dark mode"})
seq_msg = db.seq
db.put("beliefs", "dark_mode", {"value": True},
caused_by=[seq_msg], evidence="user_message", confidence=0.95)
db.query('FROM beliefs WHERE _id = "dark_mode" TRACE caused_by') # → msg_1
db.query('FROM inputs WHERE _id = "msg_1" TRACE caused_by REVERSE') # → dark_mode
# Relations + graph traversal
db.link("users:alice", "follows", "users:bob")
db.query('FROM users WHERE _id = "alice" TRAVERSE follows')
# Hash-chain integrity
assert db.verify() # cryptographic proof — no tampering
# SQL, Redis, MongoDB compatibility adapters
from nedb import sql_exec, RedisCompat, MongoClient
sql_exec(db, "SELECT * FROM users WHERE status = 'active' ORDER BY age DESC")
r = RedisCompat(db); r.execute("HSET", "user:1", "name", "Alice")
MongoClient(db)["users"].find({"status": "active"}).sort("age", -1).to_list()
Node.js
import { NedbCore } from "nedb-engine";
const db = new NedbCore(); // in-memory
// const db = NedbCore.open("./data"); // durable
db.createIndex("users", "status", "eq");
db.put("users", "alice", JSON.stringify({ name: "Alice", age: 31, status: "active" }));
// Time-travel
const snap = db.seq(); // BigInt
db.put("users", "alice", JSON.stringify({ name: "Alice", age: 32, status: "retired" }));
JSON.parse(db.getAsOf("users", "alice", snap)).age; // → 31
// Full NQL
const rows = db.query('FROM users WHERE status = "active" ORDER BY age ASC');
rows.map(r => JSON.parse(r));
// Tamper evidence
db.verify(); // → true
db.head(); // → 64-char BLAKE2b commitment hash
db.seq(); // → BigInt
nedbd — the concurrent server daemon
nedbd runs NEDB as a long-lived process with an HTTP/JSON API and an optional RESP2 wire protocol. Built on a single-writer group-commit sequencer — parallel reads, batched durable writes, one hash-chain per database, zero write-write races.
nedbd # :7070, data ./nedb-data
NEDBD_RESP2_PORT=6380 nedbd # also speak RESP2 (redis-cli compatible)
nedbd --log-level 2 # 0=errors 1=requests 2=deploy 3=verbose
# Create a database with seed data and relations
curl -X POST :7070/v1/databases -d '{
"name": "shop",
"init": {
"indexes": [["users","status","eq"]],
"seed": {"users": [{"_id":"u1","name":"Alice","status":"active"}]},
"links": [["users:u1","buys","orders:o1"]]
}}'
# Query (full NQL including time-travel and bi-temporal)
curl -X POST :7070/v1/databases/shop/query \
-d '{"nql":"FROM users WHERE status = \"active\" ORDER BY name ASC"}'
# Verify the hash chain
curl :7070/v1/databases/shop/verify
# MongoDB-compatible endpoint
curl -X POST :7070/v1/databases/shop/mongo \
-d '{"collection":"users","op":"find","filter":{"status":"active"},"limit":10}'
From redis-cli — no Redis installation needed:
redis-cli -p 6380 SELECT shop
redis-cli -p 6380 SELECT shop EVAL 'FROM users SEARCH "alice"' 0
redis-cli -p 6380 SELECT shop EVAL 'FROM users AS OF 10 WHERE status = "active"' 0
redis-cli -p 6380 SELECT shop EVAL 'FROM beliefs TRACE caused_by' 0
NQL — the NEDB Query Language
FROM <collection>
[ AS OF <seq> ] transaction time (when was it written?)
[ VALID AS OF "<date>" ] valid time (when was it true in the world?)
[ WHERE <field> <op> <value> (AND ...) ] op: = != < <= > >=
[ SEARCH "<text>" ] full-text search
[ ORDER BY <field> [ASC|DESC] ]
[ TRAVERSE <relation> ] graph traversal
[ TRACE caused_by [REVERSE] ] causal provenance (why? / what did this cause?)
[ LIMIT <n> ]
[ GROUP BY <field> [COUNT|SUM f|AVG f|MIN f|MAX f] ]
Combine both time axes:
# What did the system know at seq 200 about what was true on 2024-02-15?
db.query('FROM policy AS OF 200 VALID AS OF "2024-02-15"')
Performance (v1.0.x · Rust native · Linux x86_64 VPS)
| Operation | Throughput | Notes |
|---|---|---|
| PUT (Rust napi, per-op FFI) | ~70K/s | FFI-bound; batch path: ~15K writes/s group-commit |
| GET (Rust napi, per-op FFI) | ~330K/s | FFI-bound |
| NQL query (Rust engine) | ~23 µs | 5× faster than pure-Python (~120 µs) |
| Python PUT (AOF + fsync) | ~7K/s | Durable, per-op |
| Python GET (in-process) | ~1.3M/s | Zero socket hop |
Architecture
┌──────────────────────────────────────────────────────────┐
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 │
└─────────────────────────────────┘
Compatibility adapters: SQL · Redis · MongoDB
Wire protocols: HTTP/JSON · RESP2
Encryption: AES-256-GCM at-rest (TMK/DEK double-envelope)
Repo layout
python/nedb/ reference engine (pure Python — always-works baseline)
rust/
nedb-core/ production Rust engine (shared by both runtimes)
nedb-py/ maturin PyO3 binding → PyPI native wheels
nedb-node/ napi-rs binding → npm native addons
tests/ engine + concurrent + causal + bitemporal + deploy tests
examples/ resp2_python.py resp2_demo.sh
Roadmap
- Hash-chained append-only log — tamper evidence, replay protection, idempotency
- MVCC time-travel —
AS OF seq - Bi-temporal —
VALID AS OF "date"(transaction time + valid time) - Causal Write Provenance —
caused_by,evidence,confidence,TRACE - Durable AOF persistence + snapshot checkpoints
- Concurrent group-commit sequencer (nedbd, 15K writes/s under load)
- AES-256-GCM at-rest encryption (TMK/DEK double-envelope)
- SQL / Redis / MongoDB compatibility adapters
- RESP2 wire protocol (redis-cli / redis-benchmark compatible)
- Rust native core — napi-rs (npm) + maturin PyO3 (PyPI)
- Self-healing chains (auto-repair structural gaps, detect real tampering)
- Merkle inclusion proofs — prove a document existed at a specific time to a third party
- Git-style branching — fork database state, experiment, merge or discard
- Agent Memory SDK —
Memory.remember()/Memory.recall()/Memory.trace() - Live query subscriptions (SSE) — push diffs when query results change
NEDB Studio
Prompt-to-database scaffolding GUI with schema graph, NQL console, time-travel slider, causal provenance panel, and MongoDB/SQL/Redis tabs. Deploy from a description, query live data, edit inline.
studio.interchained.org · github.com/Eth-Interchained/nedb-studio (GPLv3)
Repos
| Repo | Description |
|---|---|
| Eth-Interchained/nedb | Canonical source — engine, Rust core, CI |
| Eth-Interchained/nedb-studio | Studio UI (GPLv3) |
| aiassistsecure/nedb | Production mirror |
| aiassistsecure/nedb-studio | Production mirror — studio |
Packages: PyPI nedb-engine · npm nedb-engine
License
See LICENSE file. · © INTERCHAINED, LLC — interchained.org
Authors
Built by Mark Allen Evans Jr. (INTERCHAINED, LLC) with Claude Sonnet 4.6 on Hyperagent.
"Take one idea, turn it into an LP, then an app, then a system, then a platform, then infrastructure that is irreplaceable."
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nedb_engine-1.1.0.tar.gz.
File metadata
- Download URL: nedb_engine-1.1.0.tar.gz
- Upload date:
- Size: 66.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d7c5a68e8fd3084a76019829a6c5ef448714e6b4b12c6850a11c3c98b2125c4
|
|
| MD5 |
1183a1ea29b75783aee1986d63f68278
|
|
| BLAKE2b-256 |
e11a2573c5494634464a7494c335ff7102df553113e6162bbeb26f9b2ca8bde2
|
File details
Details for the file nedb_engine-1.1.0-py3-none-any.whl.
File metadata
- Download URL: nedb_engine-1.1.0-py3-none-any.whl
- Upload date:
- Size: 77.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a3e616b58c64df964bbc9c630c03d23eecc00aac10da498709cdcc5d2f984e6
|
|
| MD5 |
c74d17d0173d9539d97955214cee24fa
|
|
| BLAKE2b-256 |
d53efc985b02f6ea0434a2b4cf682799dfae95a697bb094afe8432d8172799e1
|
File details
Details for the file nedb_engine-1.1.0-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: nedb_engine-1.1.0-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 356.1 kB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2e79ee6d406b1b0c78e9e223fc045fc67d35a69b5e04bd06146875f179f1992
|
|
| MD5 |
3720d03cdeea31a5ce609736fdef67dc
|
|
| BLAKE2b-256 |
8dcac25109145b620196b750bb1303e476c4817b622a8bc6cf7e946fa533b05c
|
File details
Details for the file nedb_engine-1.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: nedb_engine-1.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 472.9 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fe30e80d11406b22a24b673969bcbdc34780ed40e7bc0d97dcc26b24b320832
|
|
| MD5 |
fe05053a1c8b39c833d807a523e2adf0
|
|
| BLAKE2b-256 |
ab73d7acf53e9af0cb67fb3875eafff1c8c726aaefc7f28e4bd90e9bdfa52c03
|
File details
Details for the file nedb_engine-1.1.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: nedb_engine-1.1.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 421.0 kB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de8ac4a0c9d889559a4e51298403c4fe241b2e66a3885df0a0709806c71fab5c
|
|
| MD5 |
61ee36b73f100d247fd71c4cfbc244b3
|
|
| BLAKE2b-256 |
242dc9ebf935062c6660b203798ff7f9ca694f71821dea531ffa090b677f720a
|