May 14, 2021·4 min read·engineeringrqlitedatabase-designraftconsistency

The rqlite catalog update makes its database model worth examining

Philip O'Toole reports updating rqlite's Database of Databases entry. Its combination of relational storage, statement replication, and selectable read consistency needs more than one category label.

A database catalog is useful only when its categories preserve distinctions that matter to a user. In his May 14 post about Database of Databases, Philip O'Toole says he recently updated rqlite's entry. He describes the catalog as searchable by properties including storage model, durability, and query interface. The post reports an update, not the project's first inclusion in the catalog.

Those separate properties are useful for understanding rqlite. Calling it relational identifies how applications can model and query data. Calling it distributed identifies another part of its behavior, but does not establish how replication works or which node answers a read. The interesting question behind the catalog entry is which responsibilities SQLite supplies and which rqlite adds around it.

I value rqlite's proportionality. It supplies replicated relational state without requiring the application to choose a much larger database system solely to gain a cluster. A catalog description is most useful to me when it preserves the operating limits that come with that choice.

Relational queries do not describe the replication unit

The README from the April 5.12.0 release describes SQLite as the storage engine and Raft as the consensus mechanism. It also explicitly identifies statement-based replication. SQL statements enter the Raft log before the nodes execute them against their local databases.

That replication unit creates a restriction. The README says that only deterministic statements are safe, and uses an insert containing random() as a counterexample. If each node independently evaluates a value-generating function, the same statement can produce different local values. A relational query interface does not remove that replication concern.

An application can instead provide a value as part of the request when it needs the same value everywhere. The general reason is the replicated operation's content. Replicas need an agreed change that produces corresponding state, rather than independent choices whose equality the log never established. The documented limitation belongs in an evaluation of the database, even though a catalog can summarize its query interface as SQL.

The README also warns against changing an underlying on-disk SQLite file directly. Such changes do not enter rqlite's replication process. The supported write path is the service's HTTP API. Sharing a storage engine with a local application database therefore does not make direct file editing an equivalent operational interface.

Memory storage and durability are different properties

The same tagged README says rqlite uses an in-memory SQLite database by default, with an on-disk option. It identifies the Raft log as the authoritative store written to disk and explains that the database can be reconstructed at startup. That separates the working representation used for SQL from the retained history used for reconstruction.

This is exactly why storage model and durability deserve separate catalog fields. Describing the SQL database as in-memory would be incomplete if a reader inferred that all data disappears when the process exits. Describing the service as durable would also be incomplete if a reader assumed every SQL operation goes directly to a persistent SQLite file.

The service's architecture includes both facts. They apply to different components and phases of operation. An evaluator needs the relationship between them to understand startup and recovery, not merely a list of labels.

A read has an explicit consistency choice

The read-consistency documentation in the same tag distinguishes none, weak, and strong. With none, a node reads its local SQLite database without checking whether it is leader. The weak mode checks its local leader state first. With strong, the query goes through Raft consensus and requires quorum contact.

curl -G 'localhost:4001/db/query?level=strong' \
  --data-urlencode 'q=SELECT 1'

This example selects the documented strong mode for a simple query. The consistency choice belongs to the request. A different request can choose local reading, accepting that the node may be behind or disconnected from ongoing updates.

The documentation also offers freshness for none, checking how much time has passed since contact with the leader. It ignores that option for the other consistency levels and when its value is zero. That is a particular contact-age rule, not a universal proof that a local result contains every recent write.

I find these explicit choices useful because applications do not always need the same read behavior for every operation. A catalog category such as distributed SQL cannot communicate the latency and staleness decisions by itself. The request-level options give those decisions an actual interface.

O'Toole's short announcement is therefore a useful prompt to read the system description behind the entry. The documented database combines relational querying with statement replication and a persistent Raft history, while letting callers choose how a read consults the cluster. Those distinctions explain where rqlite fits more accurately than treating the catalog update as a new database capability.