db-20 — Broader Ideas

The lab is deliberately small. Here is the menu of extensions that keep the same cross-language exam structure intact.

Elections

Add a term bump path. Replace fixed leader_idx = 0 with a leader elected by randomised timeout (or a deterministic priority list, if you want to keep cross-language byte identity). The snapshot already serialises current_term, so the wire format does not need to change. New invariant to test: after a leader change, every healthy replica still converges to the same snapshot.

Linearizable reads

Currently reads are direct state_machine.get(k). To make them linearizable, gate every read through a "read index" — leader confirms it is still leader by exchanging heartbeats with a quorum, then returns the value at commit_index. The byte-identity exam stays the same; you add a TestReadIndexBlocksUntilQuorum-style scenario.

Log compaction / snapshot install

Today heal() ships the entire log. For long-running clusters that is unbounded. Add Replica::compact(up_to_idx) that drops the prefix and records a CompactedSnapshot at the head; change try_append to also accept "follower has snapshot_idx == prev_idx - delta". The exam scenarios still pass because the applied state is unchanged.

Multi-key transactions

Replace Op::Put with Op::Txn(Vec<KeyOp>) and apply atomically. This is a small, well-scoped extension that nudges the lab toward db-13 (transactions and MVCC) territory.

Membership changes

Add a JointConsensus op (Raft §6) that switches the cluster's quorum during a configuration change. Trickier — the snapshot needs to include the active config — but a worthy follow-on if you want to see why "just add a node" is a real problem.

Disk persistence

Persist the log to a file (use db-01's pwrite-and-fsync pattern). Test crash recovery by tearing down a replica and reconstructing it from the log file. The snapshot bytes do not change.

Learner replicas

Add a replica role that receives entries but does not count toward quorum. Useful for read scaling. The snapshot bytes do not change.

Gossip-style membership

Replace the static replica list with a SWIM-style gossip layer that discovers and evicts replicas. Far more invasive — at this point you are building etcd.

Bridges to other labs in the repo

ExtensionBuilds on which other lab?
Disk persistencedb-01 (storage primitives), db-03 (WAL)
Linearizable readsdb-16 (distributed fundamentals)
Multi-key transactionsdb-13 (transactions and MVCC)
Compaction / snapshotdb-09 (leveldb), db-21 (storage advanced)
Real elections + RPCsdb-17 (raft)
Multi-region / quorum mixdb-22 (perf & benchmarking)