NEDB v1.2.0 — Redis Layer-2: Backfill + Write Shadowing
NEDB can now wrap any existing Redis connection and retroactively absorb all historical data plus auto-chain every future write into its hash-verified, time-traveling log — in three lines.
What's new
CollectionMapping — teach NEDB your key structure
Map Redis key glob patterns to NEDB collections with a custom id extractor and value parser.
register() — chainable collection registration
(r.nedb
.register("driver:*", collection="driver", value_parser=json.loads)
.register("trip:*", collection="trip", value_type="hash")
)backfill() — one-time import of all existing Redis data
Scans Alice's existing Redis keys via SCAN and imports them into NEDB's hash chain in one pass. Returns the number of keys imported. Evidence is tagged "backfill" on every imported record.
imported = r.nedb.backfill() # → 6 (scanned and imported)shadow_writes = True — all future surface-1 writes auto-chain
Once enabled, every r.set(), r.hset(), r.setex(), etc. is silently mirrored into NEDB alongside the normal Redis write. Alice's app code changes zero lines.
r.nedb.shadow_writes = True
r.set("driver:d1", json.dumps({"name": "Bob", "status": "active"}))
# goes to Redis AND into NEDB's hash chain automaticallyFull three-step migration
import redis, json
from nedb import wrap_redis
# ONE LINE — Alice's app doesn't change
r = wrap_redis(redis.Redis("localhost", 6379), db_name="rideshare")
# Step 1 — register key patterns as NEDB collections
(r.nedb
.register("driver:*", collection="driver", value_parser=json.loads)
.register("trip:*", collection="trip", value_type="hash")
)
# Step 2 — backfill all existing Redis data into NEDB (one-time)
imported = r.nedb.backfill()
print(f"Imported {imported} existing keys")
# Step 3 — shadow all future surface-1 writes
r.nedb.shadow_writes = True
# Alice's existing app — zero changes
r.set("driver:d1", json.dumps({"name": "Bob", "status": "active", "lat": 37.77}))
r.hset("trip:t1", mapping={"status": "en_route", "driver_id": "d1"})
# New NEDB features on the same connection
active = r.nedb.query('FROM driver WHERE status = "active" ORDER BY lat ASC')
# Time-travel
snap = r.nedb.seq
r.set("driver:d1", json.dumps({"name": "Bob", "status": "offline"}))
past = r.nedb.get_as_of("driver", "d1", snap) # {"status": "active", ...}
# Causal provenance
r.nedb.put("dispatch", "e1",
{"trip_id": "t1", "driver_id": "d1", "algo": "nearest"},
caused_by=[r.nedb.seq - 1],
evidence="inference",
confidence=0.97)
r.nedb.query('FROM dispatch WHERE _id = "e1" TRACE caused_by')
# Tamper evidence
r.nedb.verify() # True
r.nedb.head() # 64-char BLAKE2b commitment hashIsolation guarantee
NEDB never writes to Alice's namespace. It owns only:
| Key | Type | Purpose |
|---|---|---|
nedb:{db_name}:oplog |
Redis Stream | append-only op log |
nedb:{db_name}:snapshot |
Redis Hash | checkpoint |
nedb:{db_name}:meta |
Redis Hash | index config |
Local demo (no Redis server needed)
pip install nedb-engine fakeredis
git clone https://github.com/Eth-Interchained/nedb
cd nedb
python3 examples/fakeredis_demo.py
# 29/29 checks passedTest coverage
- 74/74 tests passing (
python3 tests/test_wrap_redis.py) - 30 new tests covering: backfill, write shadowing, hset merge, time-travel through shadows, full pipeline + restart
Install
pip install nedb-engine==1.2.0
npm install nedb-engine@1.2.0Changelog
| Version | Highlight |
|---|---|
| 1.2.0 | wrap_redis() backfill + write shadowing — register(), backfill(), shadow_writes |
| 1.1.0 | wrap_redis() — NEDB as a Redis layer-2, dual surface |
| 1.0.5 | License → GPL-3.0-or-later, npm homepage fix |
| 1.0.3 | Rust NQL integer/float comparison fix |
| 1.0.2 | Rust AS OF index bypass fix |
| 1.0.1 | napi-rs binding rewrite |
Built by INTERCHAINED LLC × Claude Sonnet 4.6
Docs: nedb.aiassist.net