rqlite turns 10: Lessons from a decade of building Distributed Systems

4 hours ago 1

rqlite is a lightweight, open-source, distributed relational database written in Go, which uses SQLite as its storage engine and Raft for consensus.

Ten years ago, I tagged the first release of rqlite—a project I started to explore distributed consensus, to learn Go, and to build something useful. I had no roadmap, no plans for scale, and certainly no idea it would still be active a decade later.

But here we are. Over those years, rqlite has grown: in adoption, in technical depth, and in the range of decisions I’ve had to make—not just as an engineer, but as a kind of reluctant product owner. This post distills some of the most important lessons I’ve learned—from design and process choices, to feature selection, community feedback, and missed chances I still think about.

What worked—and what I wish I’d done sooner

Go was the right choice. I started rqlite to learn Go, and I haven’t looked back. I’ve enjoyed its minimalist feature set, it mindset, and its focus on clarity. These days, I’m not interested in picking up new languages—I want to ship features. Learning something new just to learn it isn’t worth slowing down what I already know how to do well. In a sense I’ve been deeply influenced by my time at Google, where impact — not effort — is what matters.

I hesitated too long to build rqlite.io. A real homepage with docs and identity could’ve helped earlier. I wasn’t trying to “market” anything, so I put it off. In hindsight, discoverability matters.

Cross-platform builds came late—but they weren’t hard. For years I assumed it would be complicated, so I put it off. Then I looked at how Mailpit handled cross-platform builds, and it clicked. Ironically, I only learned about Mailpit because its author wanted to add rqlite support.

Docker was a growth catalyst. After I started publishing Docker images, downloads surged. rqlite has now been pulled over 750,000 times. I should have done it sooner—but better late than never. Similar to cross-platform builds, it turned out to be easier than I expected.

Kubernetes was a good match. With help from the community, rqlite integrated well into Kubernetes. The way Kubernetes handles load balancing and service discovery fits naturally with rqlite’s architecture.

Testing continues to pay off. Every pull request triggers over 600 Go unit tests, plus an extensive Python-based end-to-end suite. The result? High velocity (when I have time to code), few regressions, and just five reports of production panics in 10 years. CI was one of the first processes I put in place, and has shown its value over the years

Stable API. rqlite’s HTTP API hasn’t had a single breaking change since version 2, which I released 9 years ago. That stability builds trust—and avoids rewriting client libraries. It also keeps my user base stable. It’s difficult to grow your user base so doing anything to shrink it would be a self-inflicted wound. Stability isn’t just technical discipline—it’s strategic. Any breaking change risks undoing years of quiet adoption.

Referential snapshotting was technically challenging. It meant digging into SQLite’s file formats and internal behaviors. Inspired by the excellent work of Ben Johnson and Litestream it was nerve-wracking — what if I introduced a subtle bug, only exposed after weeks of minor data loss? But it was worth it—it unlocked large dataset support.

What I still think about

Change Data Capture (CDC) might be the last big feature. It’s useful, it’s important, and it feels like the final core capability. But I won’t ship a half-baked implementation though the foundation has been laid. rqlite is partly an intellectual exercise—I want clean, understandable systems. Iteration is fine, but I’ll be clear about limitations.

rqlite was ahead of its time. It was the first system to combine Raft with SQLite. That looked odd in 2014. Today, there’s Turso, dqlite, SQLite Cloud—similar models, louder megaphones. I’m glad others saw the same potential, perhaps I should have marketed more aggressively earlier.

That SQLite bug. One of rqlite’s load tests uncovered a real bug in SQLite itself. I blogged about it and it remains one of my most-read posts. It also validated how far rqlite had come—from a side project to something that could stress-test one of the most trusted codebases in the world.

Distributed systems are often misunderstood. They attract interest, but not always depth of thought. Too often, they’re treated as black boxes—tools that magically solve hard problems. But they’re not panaceas. People frequently conflate reliability with performance, assuming the same architecture can optimize for both. It rarely does.

Why I still do this after 10 years

I enjoy it. Programming gives me clarity. Unlike management, the problems are solvable, testable, and finite. It’s a satisfying contrast to a world of meetings and ambiguity.

It keeps me sharp. rqlite has taught me tools and technologies I wouldn’t touch in my day job: Helm, Docker, Kubernetes, and SQLite internals. I’m still learning.

It keeps me honest. I don’t know if it makes me a better manager, but it makes me a more empathetic one. I still feel what it’s like to hit a bug or wrestle flaky tests. That matters.

It’s therapeutic. When I write code, I learn about computers. When I manage, I learn about myself. Both matter, but in different ways.

It’s credibility, earned slowly. A decade of shipping, testing, and listening builds trust. You can’t self-declare credibility. You do the work and let others decide. While I don’t know everything, developing rqlite means I do know at least one thing deeply.

Next Steps

If you’re curious, you can explore the project on GitHub. If you want to try it, check out the homepage. If you’ve used it, contributed, or just followed along—thank you. This post is for you too.

Read Entire Article