Why one store
The seam is the cost.
A database, a search engine, a vector index, a cache, a queue, an event log and something holding the files are each good at their own job. What none of them owns is the seam between them — and the seam is where the write that cannot be made atomic lives, along with the reconciliation job, the fusion step, the provenance convention half the pipeline forgets, and a dozen things to upgrade.
The same work, two architectures
No product is named here, on purpose. The comparison that matters is between shapes of system, and it holds whichever ones you picked.
| What you are doing | A stack and its seams | One store |
|---|---|---|
| A write that touches text, an embedding and a link | Three or four writes, in an order you chose, with no way to make them atomic | One transaction — all of it lands, or none of it does |
| A failure half way through that write | An embedding with no text, or a chunk with no vector, found later by a job | There is no half way through |
| A read that filters and ranks | A query per system, intersected in application code | One statement; the store resolves the filter and the ordering together |
| Ground truth for measuring recall | A second system, trusted to tell you how wrong the first one is | The same store — exact until the statement says APPROXIMATE |
| Where an answer came from | A column convention, kept by every writer that remembers to | An edge — a traversal, and data rather than a naming scheme |
| A cache, a lock and a rate limit beside the data | Another service, its own failure modes, and a key that outlives the record it described | A space: keys that expire, counters, SET … IF ABSENT — in the same transaction as the record |
| Events several parts of the application read | A broker, plus an offset store, plus the question of what happens between committing one and the other | A topic whose reader's position commits with what the reader writes here — once per message |
| Words and meaning ranked together | Two queries and a fusion step you write, tune and own | ORDER BY FUSE — by where each record came in each order, never by adding a score to a distance |
| Standing it up to try | Several services, their versions, and the compose file between them | One binary; in memory if you do not even want a directory |
| Operational surface | A dozen systems, each with its own backup, upgrade, auth model and failure modes | One process, one backup, one grant model, one upgrade |
Not the fastest at any one thing. Enough at all of them.
This is the trade, and it is better said here than discovered. A system built for one job — a search engine, a broker, a cache — will beat a general store at that job, and there is no benchmark on this site claiming otherwise, because none has been measured and published. Most projects never push any one of those jobs to where the difference shows. What they do pay for, every week, is running all of them: the versions, the backups, the auth models, the upgrades, and the reconciliation between them. That cost is the one a single store removes.
It grows with the project rather than being replaced by it. The same binary runs in memory for a test, on a directory for a service, with followers for copies, with automatic failover when a leader is lost, with tables split by key range across machines, and with two writers on one range. Each step is a declaration, not a migration to a different product.
And a project may outgrow one part of it. The data is one log behind a published protocol and five clients, so moving one workload to a specialist is a decision you take when the numbers say so — not a cost you pay on the first day, for a load you may never have. We work to make every engine as good at its own job as it can be; we do not promise it will be enough forever.
Where a single store is the wrong answer
A page that only lists advantages is a page that has not been checked. These are the cases where the argument above does not apply, and saying so is cheaper for both of us than finding out in week three.
- You need a dataset that reshards itself as it grows. Clustering, replication, failover and sharding by key range are in the released engine, and a split table's shards are split and merged by statement — but nothing splits a table on its own, a split moves no record already written, and the largest shard has to fit one machine.
- Your embeddings are the whole workload and run to billions of vectors with a dedicated recall and latency budget. A specialist index will beat a general store at its own game.
- Your existing stack already works and the seam is not costing you anything you can name. Replacing a system that is not hurting is how a quarter disappears.
- You need a mature ecosystem of connectors — dashboards, CDC sinks, managed hosting. This is a young engine with a published protocol, not a marketplace.
More than one machine
Clustering, replication and sharding.
Distribution shipped in 0.2.0-beta, and this table is the honest state of it. A row marked Today is behaviour you can run right now; one row is still direction, and it is marked as direction so that nothing on this site has to be walked back later. The shapes a deployment can take, and what each one costs, are on their own page rather than repeated here.
DEFINE NODE says what this machine is and where it answers; DEFINE REPLICA says which peers exist. INFO FOR NODE reads both back in one answer. The topology is in the catalog, so it is backed up; the identity is not, so a restored node does not inherit someone else's.
Taking writable away is how a node is drained, and it stays readable throughout.
The log is written out and replayed back, with a sequence bound on either end.
A namespace declares how many copies the cluster keeps and a peer subscribes to some of them, so replication is per namespace rather than per machine. Switching it on for a namespace that already holds data brings the history across with no repair step.
A leader writes under a lease it renews against a majority and refuses writes before that lease expires, on monotonic elapsed time. Losing one is noticed by a heartbeat on the peer link before the slower awareness round sees it.
A range can be declared multi-master. What that gives up is single-copy semantics, so a write concurrent with the stored version is refused and names both versions and the node that wrote the other one.
A table declared with SPLIT AT is split by key range. Each shard is logged, led and replicated on its own, and a node holding part of a table answers a read of all of it or refuses.
A split table's shards are split, merged and moved to another leader by statement while it serves. A split moves no record already written, a table declared without SPLIT AT cannot be split, and nothing splits a table on its own.
The part that already exists is the part that is easiest to get wrong later: a node’s identity and the cluster’s topology are stored in two different places on purpose. Identity stays local, so a node restored from another node’s backup does not inherit writable and start accepting writes the real writer never sees. Topology travels in the backup, so a cluster rebuilt from one does not come up believing it is alone. Neither failure would announce itself, which is why the split was decided before the replication was written.
writable and start accepting writes the real writer never sees, and a cluster rebuilt from one backup does not come up believing it is alone. The dashed band is the honest remainder: what the drawing shows is what runs today.DEFINE NODE ROLES serving, writable ENDPOINTS 'here:9000';
-- this machine; local, and deliberately not in a backup
DEFINE REPLICA second AT 'there:9001' ROLES serving, writable;
-- the topology; in the catalog, and deliberately in a backup
INFO FOR NODE;
-- both halves, in one answerProgress is reported in the documentation rather than announced here, so the page describing a capability and the capability itself land together.