Lux Skills Reference
Lux ZapDB - Embeddable Key-Value Store
ZapDB serves as the low-level storage engine across the Lux blockchain stack and is the backend for the Hanzo ORM's ZAP driver.
Overview
ZapDB is a fork of BadgerDB (dgraph-io/badger) published as github.com/luxfi/zapdb/v4. It is an embeddable, persistent, high-performance key-value database written in pure Go. ZapDB uses an LSM tree with a separate value log (WiscKey design) to achieve high read and write throughput simultaneously, with concurrent ACID transactions using serializable snapshot isolation (SSI).
ZapDB serves as the low-level storage engine across the Lux blockchain stack and is the backend for the Hanzo ORM's ZAP driver.
When to use
- Embedding a persistent key-value store in Go services on the Lux stack
- Storing blockchain state, transaction indices, or consensus metadata
- Building applications that need ACID transactions with SSI guarantees
- Needing an SSD-optimized pure Go database (no CGo required)
- Using the Hanzo ORM with the ZAP backend driver
Hard requirements
- ALWAYS import
github.com/luxfi/zapdb/v4-- NEVERgithub.com/dgraph-io/badger - Go packages stay at v4.x.x; v4.0.0 and v4.3.0 are retracted
- The Go package name is
badger(import path ends with zapdb/v4, but package isbadger) - Close the DB with
db.Close()to prevent data corruption - All mutations must happen inside transactions (
db.Updateordb.NewTransaction)
Quick reference
| Item | Value |
|---|---|
| Repo | github.com/luxfi/zapdb |
| Module | github.com/luxfi/zapdb/v4 |
| Go version | 1.26.1 |
| Package name | badger |
| License | Apache 2.0 |
| Retracted | v4.0.0, v4.3.0 |
| CLI binary | badger (in badger/ subdir) |
Core Concepts
Directory structure
luxfi/zapdb/
db.go -- DB type: Open, Close, transaction management
txn.go -- Transaction: Get, Set, Delete, Commit, Discard
iterator.go -- Iterator: prefix scan, seek, key-value access
batch.go -- WriteBatch for bulk writes
stream.go -- Concurrent key-range streaming
merge.go -- MergeOperator for read-modify-write
backup.go -- Protobuf backup/restore
errors.go -- All exported error sentinels
options.go -- Options with builder pattern (WithX methods)
compaction.go -- LSM compaction logic
value.go -- Value log management
levels.go -- LSM level management
memtable.go -- In-memory table (skiplist-backed)
key_registry.go -- Encryption key rotation
options/ -- CompressionType, ChecksumVerificationMode
table/ -- SSTable implementation
skl/ -- Skiplist (memtable backend)
pb/ -- Protobuf definitions
fb/ -- FlatBuffers definitions
y/ -- Internal utilities (WaterMark, Slice)
trie/ -- Trie data structure
badger/ -- CLI tool
main.go -- CLI entry point (jemalloc, pprof)
cmd/ -- CLI subcommands
backup.go, restore.go, info.go, flatten.go,
bench.go, stream.go, rotate.go, bank.goBasic usage
// Open database
opts := badger.DefaultOptions("/tmp/zapdb")
db, err := badger.Open(opts)
if err != nil {
return err
}
defer db.Close()
// Write
err = db.Update(func(txn *badger.Txn) error {
return txn.Set([]byte("key"), []byte("value"))
})
// Read
err = db.View(func(txn *badger.Txn) error {
item, err := txn.Get([]byte("key"))
if err != nil {
return err
}
return item.Value(func(val []byte) error {
fmt.Printf("value: %s\n", val)
return nil
})
})Options
// Default: good for most use cases
opts := badger.DefaultOptions("/path/to/data")
// LSM-only mode (values collocated with keys, less disk usage)
opts := badger.LSMOnlyOptions("/path/to/data")
// In-memory mode (no persistence)
opts := badger.DefaultOptions("").WithInMemory(true)
// Common tuning
opts = opts.
WithSyncWrites(true). // Durability on hard reboot
WithCompression(options.ZSTD). // ZSTD compression
WithBlockCacheSize(512 << 20). // 512MB block cache
WithNumCompactors(4). // Compaction workers
WithEncryptionKey(key). // AES encryption (16/24/32 bytes)
WithReadOnly(true) // Read-only modeKey features
| Feature | Details |
|---|---|
| Design | LSM tree + value log (WiscKey paper) |
| Transactions | ACID with SSI, concurrent read-write |
| Compression | Snappy (default), ZSTD, None |
| Encryption | AES-128/192/256 with key rotation |
| TTL | Per-key expiration via txn.SetEntry |
| Versioning | Multi-version (configurable versions per key) |
| Streaming | Concurrent iteration over key ranges |
| Merge ops | Read-modify-write via MergeOperator |
| Backup | Protobuf-encoded incremental backup/restore |
| Pure Go | No CGo dependency |
Error sentinels
Key errors to handle (from errors.go):
ErrKeyNotFound-- Key does not existErrConflict-- Transaction conflict, retryErrTxnTooBig-- Too many writes in one transactionErrReadOnlyTxn-- Write attempted in read-only txnErrDiscardedTxn-- Reusing a discarded transactionErrDBClosed-- Operation after CloseErrEmptyKey-- Empty key not allowedErrBlockedWrites-- Writes blocked during DropAll
CLI tool
cd badger && go install .
badger backup --dir /path/to/db # Create backup
badger restore --dir /path/to/db # Restore from backup
badger info --dir /path/to/db # Show DB info
badger flatten --dir /path/to/db # Flatten LSM tree
badger stream --dir /path/to/db # Stream keys
badger rotate --dir /path/to/db # Rotate encryption key
badger bench read --dir /path/to/db # Read benchmark
badger bench write --dir /path/to/db # Write benchmarkBuild and test
# Build
go build ./...
# Run tests (requires jemalloc for full test suite on some platforms)
make test # Runs test.sh
go test ./... # Without jemalloc
# Build CLI
make badger # Compiles badger binary (downloads jemalloc if needed)
# Dependencies
make dependency # Install build deps (apt-based)Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
ErrConflict on commit | Read-write conflict in concurrent txns | Retry the transaction |
Value log GC didn't result in cleanup | No reclaimable space | Normal; GC only runs when beneficial |
| Slow reads | Block cache too small | Increase WithBlockCacheSize |
| High disk usage | Value log not GC'd | Call db.RunValueLogGC(0.5) periodically |
ErrTruncateNeeded | Corrupt value log after crash | Open with truncate option or restore from backup |
| Data directory locked | Another process has DB open | Close other instance or use WithBypassLockGuard (unsafe) |
| Memory usage too high | Large memtables or cache | Reduce WithMemTableSize and WithBlockCacheSize |
Related Skills
lux/lux-database.md-- Database layer overview for the Lux stacklux/lux-node.md-- Lux node (uses ZapDB for state storage)
Last Updated: 2026-03-13