Lux Docs
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

  1. ALWAYS import github.com/luxfi/zapdb/v4 -- NEVER github.com/dgraph-io/badger
  2. Go packages stay at v4.x.x; v4.0.0 and v4.3.0 are retracted
  3. The Go package name is badger (import path ends with zapdb/v4, but package is badger)
  4. Close the DB with db.Close() to prevent data corruption
  5. All mutations must happen inside transactions (db.Update or db.NewTransaction)

Quick reference

ItemValue
Repogithub.com/luxfi/zapdb
Modulegithub.com/luxfi/zapdb/v4
Go version1.26.1
Package namebadger
LicenseApache 2.0
Retractedv4.0.0, v4.3.0
CLI binarybadger (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.go

Basic 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 mode

Key features

FeatureDetails
DesignLSM tree + value log (WiscKey paper)
TransactionsACID with SSI, concurrent read-write
CompressionSnappy (default), ZSTD, None
EncryptionAES-128/192/256 with key rotation
TTLPer-key expiration via txn.SetEntry
VersioningMulti-version (configurable versions per key)
StreamingConcurrent iteration over key ranges
Merge opsRead-modify-write via MergeOperator
BackupProtobuf-encoded incremental backup/restore
Pure GoNo CGo dependency

Error sentinels

Key errors to handle (from errors.go):

  • ErrKeyNotFound -- Key does not exist
  • ErrConflict -- Transaction conflict, retry
  • ErrTxnTooBig -- Too many writes in one transaction
  • ErrReadOnlyTxn -- Write attempted in read-only txn
  • ErrDiscardedTxn -- Reusing a discarded transaction
  • ErrDBClosed -- Operation after Close
  • ErrEmptyKey -- Empty key not allowed
  • ErrBlockedWrites -- 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 benchmark

Build 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

IssueCauseSolution
ErrConflict on commitRead-write conflict in concurrent txnsRetry the transaction
Value log GC didn't result in cleanupNo reclaimable spaceNormal; GC only runs when beneficial
Slow readsBlock cache too smallIncrease WithBlockCacheSize
High disk usageValue log not GC'dCall db.RunValueLogGC(0.5) periodically
ErrTruncateNeededCorrupt value log after crashOpen with truncate option or restore from backup
Data directory lockedAnother process has DB openClose other instance or use WithBypassLockGuard (unsafe)
Memory usage too highLarge memtables or cacheReduce WithMemTableSize and WithBlockCacheSize
  • lux/lux-database.md -- Database layer overview for the Lux stack
  • lux/lux-node.md -- Lux node (uses ZapDB for state storage)

Last Updated: 2026-03-13

On this page