A compact Go implementation of a Raft cluster that replicates a Bolt-backed key/value database.
-
Raft core — leader election, heart-beats, log replication, safety.
-
Storage layer
- write-ahead log in BoltDB
- KV bucket with a small in-memory LRU hot-set
-
Tiny transport — JSON-over-HTTP RPC (no gRPC, no protobuf).
-
Binaries
server– start a Raft nodeclient– PUT / GET helper
-
Tests — unit, integration & fault-injection (see tests/).
Want the quickest Raft refresher?
https://thesecretlivesofdata.com/raft/
- Go 1.22 or newer
git clone https://github.com/your-org/mini_etcd.git
cd mini_etcd
go mod download# terminal 1
go run ./cmd/server/main.go -id node1 -addr :9001# terminal 2
bin/client put foo bar
bin/client get foo # → bar# term 1
go run ./cmd/server/main.go -id node1 -addr :9001 -peers node2=:9002,node3=:9003
# term 2
go run ./cmd/server/main.go -id node2 -addr :9002 -peers node1=:9001,node3=:9003
# term 3
go run ./cmd/server/main.go -id node3 -addr :9003 -peers node1=:9001,node2=:9002Wait ~½ s → one prints “became leader”.
Send PUT/GET to the leader; followers forward if you mis-address them.
All public tests live in tests/.
go test ./tests -v # run everything
go test ./tests -run AutoPrune # single case.
├── cmd/
│ ├── client/ # CLI helper
│ └── server/ # wires Raft + KV + HTTP
├── internal/
│ ├── kv/ # Bolt + LRU store
│ ├── raft/ # Raft algorithm
│ └── transport/ # JSON/HTTP RPC
├── tests/ # public tests
└── config/ # timing & pruning constants
All timings live in config/constants.go:
const (
ElectionTimeoutMin = 150 * time.Millisecond
ElectionTimeoutMax = 300 * time.Millisecond
HeartbeatInterval = 30 * time.Millisecond
PruneEvery = 2000 // entries
RetainTail = 100 // keep last N after prune
)