etcd-io/etcd
Backend (bbolt)
Source: server/storage/backend/.
Purpose
The backend is etcd's interface to bbolt — the embedded B+tree-based key-value store that holds the MVCC keyspace, lease state, auth state, cluster metadata, and version markers. Everything that ends up on disk in <data-dir>/member/snap/db flows through this package.
Directory layout
server/storage/backend/
├── backend.go # Backend interface, batchTxBuffer, defrag, snapshot
├── batch_tx.go # Buffered write transactions
├── read_tx.go # Read transactions w/ buffer overlay
├── tx_buffer.go # In-memory write buffer flushed on commit
├── config_default.go / config_linux.go / config_windows.go
├── metrics.go
├── hooks.go # Pre-commit hooks (used by mvcc and lease)
├── verify.go # Debug-only invariants
└── testing/Key abstractions
| Symbol | File | Description |
|---|---|---|
Backend interface |
server/storage/backend/backend.go |
Top-level API: BatchTx, ReadTx, Snapshot, Defrag, Hash, Commit |
backend struct |
same file | Owns the bbolt *bolt.DB, batch-tx, and metrics |
BatchTx |
server/storage/backend/batch_tx.go |
Buffered write transaction: writes to a memory buffer, periodically commits to bolt |
ReadTx |
server/storage/backend/read_tx.go |
Snapshot-isolated read view |
txWriteBuffer / txReadBuffer |
server/storage/backend/tx_buffer.go |
Per-bucket in-memory mutation buffer |
defragdbPath |
server/storage/backend/backend.go |
Where defrag's temporary file lives |
How it works
sequenceDiagram
participant Caller
participant Batch as BatchTx
participant Buf as txWriteBuffer
participant Bolt as bbolt
participant Disk
Caller->>Batch: UnsafePut(bucket, key, value)
Batch->>Buf: buffer mutation
note over Batch: every BatchInterval (100ms) or BatchLimit (10000) ops
Batch->>Bolt: bolt.Update(applyBuffer)
Bolt->>Disk: fsync
Bolt-->>Batch: ok
Batch->>Buf: clear buffered mutationsReads:
ReadTxopens abolt.Txfor the lifetime of the read.- To produce consistent semantics across in-flight writes, the read side overlays the currently buffered writes from
txWriteBufferon top of the bolt view.
Defragmentation:
- Acquires the global write lock.
- Opens a new bolt file, walks every bucket and copies the compacted contents.
- Atomically renames the new file over the old one.
Configuration knobs
| Flag / constant | Default | Effect |
|---|---|---|
--quota-backend-bytes |
0 (= 2 GiB) | Triggers a NOSPACE alarm above this size |
--backend-batch-interval |
100 ms | How often the batch tx commits if it's not full |
--backend-batch-limit |
10000 | Op count threshold for early commit |
--backend-bbolt-freelist-type |
array |
bbolt freelist type (Linux only) |
MmapSize (config_linux.go) |
1 GiB initial | mmap region size; doubles as the DB grows |
Integration points
- mvcc writes to the
keybucket throughBatchTx. - lease writes to the
leasebucket. - auth writes to
auth,authUsers,authRolesbuckets. - schema (
server/storage/schema/) defines the bucket inventory and version metadata. - maintenance (
server/etcdserver/api/v3rpc/maintenance.go) wiresSnapshot,Defrag,HashKV,MoveLeader. - etcdutl and
tools/etcd-dump-db/open the same DB format directly.
Entry points for modification
- Tuning batch behavior →
config_default.goplus the--backend-batch-*flags inserver/embed/config.go. - New bucket or column →
server/storage/schema/bucket.go. - Reducing fsync pressure → look at
BatchTx.Commitandbolt.DB.Sync.
Caveats
- bbolt holds a single global write lock; long write transactions block all writers. The batch tx exists specifically to batch many small writes into one bolt commit.
- A long-running read transaction prevents the freelist from growing, which can lead to tail-latency spikes; the apply pipeline takes care to close read txns promptly.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.