Back to blog

Building a Distributed Database with Go and Raft

·2 min read

Why Another Database?

The database landscape is crowded, but there's a gap for lightweight, embeddable distributed SQL databases. Most solutions are either:

  • Heavyweight (CockroachDB, TiDB)
  • Eventually consistent (Cassandra, DynamoDB)
  • Not SQL (etcd, Consul)

rqlite fills this gap by combining SQLite's simplicity with Raft's strong consistency guarantees.

Architecture

At its core, rqlite has three layers:

  1. SQLite for storage and query execution
  2. Raft for cluster consensus and log replication
  3. HTTP API for client communication

The Raft layer ensures that all nodes in the cluster agree on the order of writes. Each write is recorded in the Raft log, committed, and then applied to SQLite.

type Cluster struct {
  raft   *raft.Raft
  sqlite *sqlite.DB
  http   *http.Server
}

Consensus in Practice

Raft works by electing a leader. All writes go through the leader, which replicates them to followers. Reads can be served by any node, but you can also request consistent reads from the leader.

Here's the write path:

  1. Client sends SQL to leader via HTTP POST
  2. Leader appends the SQL to its Raft log
  3. Log entry is replicated to a majority of followers
  4. Entry is committed
  5. SQL is applied to the local SQLite instance
  6. Response is sent to the client

Performance

For a three-node cluster on commodity hardware, rqlite achieves:

OperationLatencyThroughput
Write~5ms~200/s
Read~1ms~1000/s
Streaming~2ms~500/s

These numbers make it suitable for applications that need reliability without the operational overhead of a full distributed database.

Lessons Learned

Building distributed systems is hard. A few lessons:

  • Testing: Use Jepsen-style testing early. Network partitions reveal bugs you didn't know existed.
  • Simplicity: Resist the urge to over-optimize. A simple design that works is better than a complex one that might.
  • Observability: Instrument everything. You can't debug a distributed system without good metrics and tracing.

"A distributed system is one in which the failure of a computer you didn't even know existed can render your own computer unusable." — Leslie Lamport

Conclusion

rqlite shows that you don't need a massive codebase to build useful distributed systems. By composing well-understood components (SQLite

  • Raft), you get a reliable, easy-to-operate database.