Library / SDK
canonical/dqlite avatar
canonical/dqlite

dqlite: a replicated SQLite engine you embed in your own process

Embeddable, replicated and fault-tolerant SQL engine.

4,389 stars255 forksCNOASSERTION

At a glance

What is it?
dqlite turns SQLite into a Raft-replicated, fault-tolerant cluster inside your application, with no external database to run. This review covers how it works, how to install it on Debian, and where it is the wrong tool.
Who is it for?
Adopt dqlite if you ship a Linux application that already owns its data and you want SQLite's file-level simplicity with automatic failover, and you are prepared to link against libdqlite or drive it through the Go bindings. Do not adopt it if you need to run on macOS or Windows, if you cannot guarantee native Linux async I/O on your kernel, or if you want a standalone database server with its own CLI and HTTP API, which is what rqlite provides.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What dqlite solves, and who it is actually for

SQLite gives you a database in a file, with no server process and no network hop. That is also its ceiling: one file, one writer, one machine. The moment an application needs to survive the loss of a node, the usual answer is to bolt on PostgreSQL or MySQL, which means operating a separate service, its backups, its upgrades and its credentials.

dqlite sits between those two positions. The README describes it as "a C library that implements an embeddable and replicated SQL database engine with high availability and automatic failover", and the acronym stands for "distributed SQLite". The library extends SQLite with a network protocol so that several instances of your application connect to each other and behave as one highly available cluster, "with no dependency on external databases".

The audience is narrow and specific. This is for teams writing a service in C, C++ or Go that already wants to own its storage layer, and whose deployment model is a small set of nodes that must agree on data. Canonical builds it, and the same design reasoning shows up in the Go bindings, which ship a demo program. If your application is a single process on a single host, dqlite adds a Raft log, a wire protocol and a cluster membership problem in exchange for nothing.

Raft, libuv and a wire protocol built for SQLite

The design highlights section of the README lists three decisions. First, the implementation is asynchronous and single-threaded, using libuv as the event loop. Second, there is a custom wire protocol optimized for SQLite primitives and data types rather than a generic SQL transport. Third, data replication is based on the Raft algorithm.

Those three choices fit together. A single-threaded event loop means no lock contention between SQLite connections inside the process, and Raft's leader election and log replication are driven by the same loop. Because the protocol is aware of SQLite's types and statement primitives, the replication path does not have to parse and re-plan arbitrary SQL on the follower side, which a generic proxy would.

The practical consequence is that a dqlite node is not a database server you connect to from outside. It is a library linked into your binary, and the cluster is a cluster of your application processes. The repository layout reflects this: include/ holds the public headers, src/ the implementation, and the build is Autotools (configure.ac, Makefile.am). If you want to write a client in another language, the README points to the wire protocol documentation at dqlite.io/docs/protocol rather than to a language-specific SDK.

Installing dqlite on Debian and running the Go demo

The README offers two paths. On a Debian-based system you can take the latest development release from the project's dev PPA:

bash
sudo add-apt-repository ppa:dqlite/dev
sudo apt update
sudo apt install libdqlite-dev

That gives you the shared library and headers. Note the word development: this is a PPA, not a stable distribution channel, so pinning is your problem.

Building from source needs pkg-config, GNU Autoconf, Automake, libtool and make, plus libuv v1.8.0 or later, SQLite v3.22.0 or later, and optionally LZ4 v1.7.1 or later, all with headers. On Debian-based distributions the README gives this dependency line:

bash
sudo apt install pkg-config autoconf automake libtool make libuv1-dev libsqlite3-dev liblz4-dev

Then the standard Autotools sequence, which installs to /usr/local by default:

bash
autoreconf -i
./configure
make
sudo make install
sudo ldconfig

The ldconfig step is there because the linker otherwise will not find libdqlite.so. To install elsewhere, replace the configure step with ./configure --prefix=/usr.

For a first real use, the README does not walk you through a cluster. It says the simplest way to see dqlite in action is the demo program shipped with the Go bindings, and links to the go-dqlite demo documentation. The repository Dockerfile shows the build order that demo depends on: build canonical/raft, install it, build dqlite, then build go-dqlite with the libsqlite3 build tag and install both dqlite-demo and dqlite. The Dockerfile pins Go 1.15.2, which is old enough that you should expect to substitute a current toolchain rather than copy it literally.

Linux only, native async I/O, and a tracing flag you will need

The compatibility section is one sentence long and it is a hard boundary: dqlite runs on Linux and requires a kernel with support for native async I/O, with an explicit note that this is not the same thing as POSIX AIO. There is no macOS build, no Windows build, and no statement anywhere in the README about other platforms. If your developers work on laptops and your production runs Linux, you cannot reproduce the runtime locally without a VM or a container.

The second limitation is observability. The only diagnostic mechanism the README documents is an environment variable. Detailed tracing is enabled when LIBDQLITE_TRACE is set before startup, with a value in the [0..5] range. The scale is counterintuitive: 0 means no traces, 5 emits FATAL records only, and 1 is maximum verbosity covering DEBUG, INFO, WARN, ERROR and FATAL. Anyone who assumes higher means louder will set 5 and see almost nothing. The README does not document log destinations, rotation or rollback procedures, so plan for that gap.

Third, static linking has its own rules. Passing --with-static-deps to configure disables code that relies on dynamically linked dependencies, and the README notes this currently only affects the test suite but should be used anyway for future compatibility. Under musl libc the default stack size is too low, and the README recommends LDFLAGS="-Wl,-z,stack-size=1048576". That is a real footgun for Alpine-style images.

dqlite versus rqlite: library or server

The most common comparison is with rqlite, and the difference is architectural rather than a matter of features. rqlite is a standalone process: you run it, it speaks HTTP, and your application talks to it over the network like any other database server. dqlite is a C library you link into your own program, and the network protocol exists so that multiple copies of your program can form a cluster. With rqlite the database is a service you deploy and monitor. With dqlite the database is part of your binary's address space, and cluster membership is something your application manages.

That distinction decides most adoptions. If you want a database you can curl, back up independently and upgrade without rebuilding your application, rqlite is the closer fit. If you are shipping an appliance or an agent that must be self-contained and must keep working when a node dies, embedding removes an entire deployment unit. The README also links a 2022 blog post comparing dqlite with rqlite and Litestream, which is worth reading as background even though it predates the current release line.

The other names that come up, LiteFS and libSQL, are different again: they start from the file and the SQLite fork rather than from a Raft library inside your process. dqlite's bet is that replication belongs in the application, not beside it.

Maintenance, releases and the licence question

The repository is not archived, and the last push was on 2026-09-18, five days before this writing. Recent releases are v1.18.7 and v1.17.4, both tagged 2026-07-02, with v1.18.6 before them on 2026-04-20. Two maintained minor lines is a reasonable sign that backports happen, and the presence of renovate.json suggests dependency updates are automated. There is a SECURITY.md, a CODE_OF_CONDUCT.md and a CONTRIBUTING.md, which is the paperwork of a project that expects outside contributors.

Upgrade cost depends on which path you took. If you consume libdqlite-dev from the dev PPA, upgrades are apt operations but you inherit whatever the PPA publishes, and the README explicitly calls it a development release. If you build from source, every upgrade means re-running autoreconf, configure and make against your pinned libuv and SQLite, and any ABI change in the public headers under include/ forces a rebuild of your application. The version is tracked in a VERSION file at the repository root, and debian/ and contrib/ hold packaging and static build helpers.

On licensing, the README states the library is released under a slightly modified LGPLv3 that includes a copyright exception allowing users to statically link the library code and release the final work under their own terms. That exception is the reason a static build is viable at all. The repository metadata reports the license as NOASSERTION, meaning no SPDX identifier was detected, so read the LICENSE file itself rather than trusting the badge. This is not legal advice; if you ship a closed-source product, have counsel confirm the exception covers your linking model.

Editorial conclusion

Adopt dqlite if you ship a Linux application that already owns its data and you want SQLite's file-level simplicity with automatic failover, and you are prepared to link against libdqlite or drive it through the Go bindings. Do not adopt it if you need to run on macOS or Windows, if you cannot guarantee native Linux async I/O on your kernel, or if you want a standalone database server with its own CLI and HTTP API, which is what rqlite provides. Before committing, verify three things: that your kernel exposes native async I/O, that your build can satisfy libuv v1.8.0 or later and SQLite v3.22.0 or later, and that you have read the LGPLv3 text with its static-linking copyright exception because the repository carries no SPDX-normalized license identifier.

Frequently asked questions

What is dqlite and how does it relate to SQLite?

dqlite is a C library that extends SQLite with a network protocol so several instances of an application can act as a replicated, fault-tolerant cluster. The README describes it as an embeddable and replicated SQL database engine, and the name stands for distributed SQLite.

How do I install dqlite on Debian or Ubuntu?

The README gives a dev PPA: add ppa:dqlite/dev, run apt update, then install libdqlite-dev. Building from source instead requires pkg-config, autoconf, automake, libtool, make, libuv1-dev, libsqlite3-dev and liblz4-dev, followed by autoreconf -i, ./configure, make and sudo make install.

Does dqlite run on macOS or Windows?

No. The compatibility section states dqlite runs on Linux and requires a kernel with support for native async I/O, which the README distinguishes from POSIX AIO. No other platform is documented.

How do I turn on dqlite tracing?

Set the LIBDQLITE_TRACE environment variable before startup. Its value ranges from 0 to 5, where 0 emits no traces, 5 emits FATAL records only, and 1 enables maximum verbosity across DEBUG, INFO, WARN, ERROR and FATAL.

What licence does dqlite use?

The README says the library is under a slightly modified LGPLv3 with a copyright exception that permits static linking and release of the final work under your own terms. Repository metadata reports NOASSERTION, so consult the LICENSE file and your own counsel.

Official sources

  1. canonical/dqlite on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/canonical-dqlite.svg)](https://hysenlabs.com/projects/canonical-dqlite)