Skip to content

What this is, in plain English ​

Sovereign Engine is a database engine — the part of a system that stores facts and answers questions about them. It is built for one specific, hard situation: the same data being written in several places on Earth at the same moment, where every copy has to end up agreeing, and where you need to know not only what the data says now, but what it said last Tuesday, and why it changed. This page explains that without assuming you have ever written database code. Nothing on it requires you to take my word: every claim links to the page that shows the evidence.

The one-paragraph version

Most databases, when two places write the same record at the same time, either pick a winner and silently discard the other fact, or make both places wait for each other to agree. Sovereign Engine does neither. It stores facts in a form where merging them is arithmetic rather than a judgement call, so any two copies that have seen the same facts arrive at the same answer — in any order, with duplicates, with the network cut and healed — without a coordinator and without waiting. It also keeps three separate clocks on every fact, so a correction adds to history instead of erasing it. It is a research preview: the core is measured on real hardware, the multi-region guarantees have been demonstrated with 100 node processes on three machines across three continents, and it is not ready to hold data you cannot afford to lose.

The problem, with a real example ​

Picture a shipping company tracking 40,000 containers. Its systems run in Singapore, Frankfurt and Virginia — not for prestige, but because a customer in Singapore should not wait for a round trip to Virginia to see where their container is.

At 03:00, a crane operator in Singapore marks container 7Y-4410 as loaded. In the same second, a scheduler in Frankfurt marks the same container as held for inspection. Two people, two continents, one container, and neither could possibly have known about the other.

Now the system has to decide what is true. And whatever it decides, it will be asked about it later — by an auditor, by an insurer, or by a customer whose cargo went to the wrong port.

Why the usual answers don't fit this case ​

There are two standard ways to handle that collision, and both are respectable engineering.

Pick a winner. Compare timestamps, keep the later write, discard the other. This is what most systems do, and it is fast. It also means one of those two facts is now gone, and nobody gets told. Worse, clocks on separate machines genuinely disagree — by milliseconds normally, by much more when one drifts — so "later" is not even a reliable notion across continents.

Make them agree first. Have the regions vote on every write before accepting it, so there is only ever one version of the truth. This is correct, it is what distributed SQL databases do, and it is the right answer for a bank ledger. The cost is physics: a round trip between Singapore and Virginia is a couple of hundred milliseconds, set by the speed of light in fibre, not by anything an engineer can optimise. Every write pays it. And when the link between regions is cut, at least one side must stop accepting writes until it comes back.

Sovereign Engine exists for the systems where neither trade is acceptable: where you cannot afford to lose a fact, cannot afford to wait for a distant region, and cannot afford to stop accepting writes when the network breaks. That combination is not most systems. It is the one I chose to build for.

The first idea: make merging arithmetic, not a decision ​

Adding numbers has a useful property: order does not matter. 2 + 3 + 5 is 10 no matter which order you add them in. Merging two shopping lists by taking everything on both has the same property — and a repeat entry changes nothing.

The engine stores state in a structure that behaves that way. Instead of a value that gets overwritten, it holds facts that combine under a rule that does not care about order, does not care about duplicates, and does not need to know which one came "first". The academic name for such a structure is a CRDT — a conflict-free replicated data type. The δ (delta) in "δ-CRDT" means the engine ships only what changed, not the whole state, each time it syncs.

The consequence is the whole point: if two nodes have seen the same set of facts, they hold the same state — guaranteed by the arithmetic, not by a protocol that has to be trusted to have run correctly. No coordinator. No voting. Nothing to wait for. A node can be disconnected for an hour, receive everything out of order and three times over, and still land on the identical answer as every other node.

In the container example, both facts survive. The container is recorded as loaded and as held for inspection, with the causal information showing they were concurrent — nothing was lost, nothing was invented, and a business rule or a human decides what to do about it. The engine's job is to lose nothing and to converge. Deciding which fact should win is a business question, and the engine refuses to pretend otherwise by silently answering it.

You can watch this converge, step by step, in the live simulations — the same algorithms, running in your browser.

The second idea: never quietly forget what you believed ​

Most databases overwrite. When a correction arrives, the previous value is gone, and the fact that anyone ever believed it is gone with it. For anything audited — finance, healthcare, insurance, logistics, aviation — that is precisely the wrong thing to lose.

So every fact here carries three clocks instead of one:

  • valid time — when the fact was true in the world;
  • system time — when this system found out about it;
  • assertion time — which revision, or claim, it was asserted under.

Three clocks let you ask a question that a single-timestamp database cannot answer: on 3 March, what did we believe the container's status had been on 1 March? The answer comes back as it genuinely stood on 3 March — including the belief that was later corrected. A correction is a new assertion layered on top of the old one, not an eraser.

This is the capability I would defend hardest, because it is the one that cannot be bolted on later. The three clocks are part of the fixed record every fact is written into; a database that started with one timestamp cannot grow the other two without rewriting all of its history.

Why this took unusual engineering ​

The ideas above are not mine — CRDTs and bitemporal modelling are established research. What is mine is the decision to make them survive contact with a machine running 32 cores flat out, where a few milliseconds of hesitation is not a hiccup but a collapse. Three constraints drove almost every implementation choice, and each was measured rather than assumed.

Memory pauses. The engine is written in Go, a language that reclaims unused memory for you — and occasionally pauses the program to do it. In ordinary software you would never notice. At tens of millions of operations a second, work arriving during a pause queues up, and the queue does not recover. So the engine takes one large block of memory at startup and manages it entirely itself, and a test gate fails the build if the busiest code path allocates even once. The measured result is zero allocations per operation there.

Where numbers sit in memory. This one is my favourite, because it is so easy to disbelieve until you see it. Two internal counters happened to be placed inside the same 64-byte block of memory — a cache line, the unit CPUs actually shuttle between cores. With 32 cores updating those two counters, every update to one invalidated the other core's copy. Throughput: about 1.1 million operations a second. Move the counters apart so they sit in separate blocks, changing nothing else, and the same code runs at over 50 million — roughly fifty times faster, at about 1.6% efficiency before the fix. Identical algorithm, identical hardware; only the memory layout changed. That measurement is why a layout checker runs over the code, why the padding is placed by hand, and why I do not let an automatic formatter reorder those structures — it has silently destroyed that spacing before.

Waiting on locks. The conventional way to stop two threads corrupting shared data is a lock: one thread holds it, the others wait. Waiting means handing control to the operating system's scheduler, and at this rate that stall is the same cliff as the memory pause. The write path uses atomic compare-and-swap instructions and a reclamation scheme that lets readers finish safely, instead of a lock. Where locks do remain, they are off the write path, and the documentation says which ones and where.

None of these are clever. They are the standard answers, applied without exception, and then measured to prove they were actually applied. The engineering claim I am making is not inventiveness. It is that the discipline held.

What is measured, and what the numbers do not mean ​

A number without its conditions is marketing. Every figure the project publishes carries the layer it was measured at, the hardware it ran on, and the range it varies over — and the most important column below is the third one, the one that says what the figure is not evidence of. On a narrow screen the table scrolls sideways; that column is worth the scroll.

What was actually measuredThe numberWhat it does not mean
The core data structure, in one process, with nothing else attached — no network, no encryption, no disk50.7–68.3 million operations/sec on 32 cores (AWS Graviton4). 50,736,038 is the floor the build gate enforcesNot the speed of the database. This is the engine room measured with the doors shut. Quoting it as a serving rate would be dishonest, so the project states the layer every time
The real write path an operator drives: network decoding, signature verification, merging into state5.7–6.0 million writes/sec on 32 coresThis is the closest figure to "how fast is it" on one machine. It is roughly ten times below the core number, because checking signatures costs real time
10,000 keys written across 100 node processes on three machines in three AWS regions (Virginia, Ireland, Sydney), then every node checked for agreementAll nodes agreed in 8.95 seconds in the published run; six of the seven logged runs before it finished between 6.6 and 8.7 seconds, with the corruption detector armedNot "always". About one run in seven, a straggling node finishes past the ten-second bar; the seventh logged run took 10.15 seconds. That is the open problem, stated below
A node killed mid-run, then restartedRecovers and matches the fleet exactly — its state fingerprint re-equals the othersProven on real multi-region hardware, not simulated on one laptop
Test, fuzz, fault-injection and benchmark code versus engine codeAbout 1.6 lines of verification per line of engineA ratio, deliberately — so it stays honest as the codebase grows

A detail that matters more than any single number: a run only counts as evidence if the check that would have caught a silent disagreement is confirmed to have been switched on. A passing run with that check off is recorded as no evidence, not as a pass. And a benchmark that regresses is written down as it came out, not re-run until it looks better.

The full evidence ledger, with hardware, toolchain and provenance for each figure, is on Verification & Status. The comparison against other databases — writes compared to writes, never a read against a write — is on the benchmark comparison.

What is not finished ​

I would rather you decide against this engine for the right reason than adopt it for the wrong one.

It is a research preview, not production software. Do not put data in it that you cannot afford to lose. The core is measured and the hard distributed guarantees have been demonstrated, but the surrounding work that makes a database boring and safe is not done.

The specific gaps, in plain terms:

  • The convergence tail. The ten-second target is met, but roughly one run in seven leaves one or two nodes straggling past it. This is a property of how updates spread between nodes, not of durability — no data is lost — and it is the current hardening target.
  • Geospatial indexing is reserved, not live. Every fact carries a field for a geographic cell, and it travels on the wire and into storage — but the pipeline that would compute those cells is built and not wired in, and the native worker it needs is not in the repository. Calling it a working geospatial index today would be an overstatement, so the docs call it a reserved axis.
  • Authorization is not in the request path. The policy engine is a pinned dependency and an experiment, not a live permission check.
  • One internal cache has no size ceiling yet. It is bounded to live state, but not to a fixed number of bytes. Bounding it properly is planned work.
  • Some capabilities are behind flags — kernel-level network steering and process-crash supervision among them — and the docs label each one rather than counting it as shipping.

That list is maintained on the honest boundary section, alongside a record of the failures that have already been found and fixed: a use-after-free on shutdown, a lock held across a disk sync, a 300-second stall traced to checkpoint writes on the commit path, a memory-exhausting read, a wrong-sized deallocation, and a missing checksum that let disk corruption pass silently. Each was found by measurement, root-caused, fixed, and then re-proven by deliberately reintroducing the bug to confirm the new guard actually fires.

I publish those because a repository that shows only successes tells you nothing useful about how the next problem will be handled.

Security, and why post-quantum already ​

Encrypted traffic can be recorded today and stored until it becomes readable. When a machine capable of breaking today's key exchange arrives, everything captured in the meantime is retroactively exposed. The defence has to already be in place by then; it cannot be applied retroactively.

So the default build negotiates a hybrid post-quantum key exchange (X25519MLKEM768) on every connection — classical and post-quantum together, so breaking either one alone is not enough. Post-quantum signatures (ML-DSA-65) are implemented and available behind a flag, with both the classical and the post-quantum signature required to verify. They are off by default for an honest reason with a number attached: a post-quantum signature is 3,309 bytes against Ed25519's 64 — about 51 times larger — and that cost belongs to the operator to accept, not to me to impose quietly. A test gate pins the ratio so it cannot drift unnoticed.

How to check any of this yourself ​

This is the part I care about most, because it is what separates a claim from a number.

  1. Clone the repository and run the tests. github.com/hr18vk/sovereign — the gates that enforce the zero-allocation rule, the memory layout, and the merge law are ordinary tests. They run on your machine.
  2. Re-run the benchmarks on the stated hardware. Every published figure names its instance class, CPU and toolchain, precisely so you can reproduce it or prove it wrong. The throughput gate deliberately refuses to run on a machine smaller than the one it claims — a 4-core result cannot be relabelled as a 32-core one.
  3. Read the decision records. Every significant architectural decision is written down with its reasoning, including the ones that were rejected and the ones that turned out to be wrong and were reversed.
  4. If a number here does not reproduce, that is a bug report I want. Open an issue. A figure I cannot defend is worse for me than a figure that is merely unimpressive.

Where this stands, and what I am working on ​

I am building this on my own. The engine is at the stage where the core is measured on named hardware, the distributed guarantees — convergence, crash recovery, durability — have been demonstrated with 100 node processes on three machines across three continents, and the work now is the tail: the last straggling node, the missing size bounds, the authorization path, and the cross-entity query index that the data model deserves and does not yet have.

What I am optimising for is not the number of features. It is that every claim on this site can be traced to something you can run.

Where to go next ​

Three doors, depending on why you are here.

The words you will meet on the other pages ​

  • CRDT — a data structure whose merge rule ignores order and duplicates, so separate copies converge without coordination. The reason no coordinator is needed.
  • δ-CRDT (delta) — the same, but syncing only what changed rather than the whole state.
  • Tri-temporal — three clocks on every fact: when it was true, when the system learned it, and which revision asserted it.
  • Off-heap / zero-GC — the engine manages its own memory instead of letting the language's automatic collector pause the program.
  • Leaderless — no node is in charge; there is no election to win and no leader whose failure stops writes.
  • Merkle root — a short fingerprint of an entire dataset. Two nodes compare fingerprints to tell, in one number, whether they agree.
  • Hot path — the code every single operation runs through. The place where an allocation, a lock, or a badly placed counter costs everything.

Engineered from first principles to solve the distributed state problem without the latency tax of traditional consensus.