Client / server
Arkeion starts life as an embedded library, but it also ships a server. Not
“another SQL server”: the point is that git and audit semantics are first-class
in the protocol — a branch per session, time-travel (AS OF), cryptographic
verify over the wire, and diff/merge as remote calls. The goal is a
verifiable cloud rather than a “trust us” one, which is the same thesis as
sovereignty.
A native protocol, not pgwire
Speaking Postgres’s wire protocol (pgwire) would buy an instant ecosystem, and it
was seriously evaluated. Native won because the things that make Arkeion worth
connecting to — attaching to a branch, migrating, diff, merge, verify over
the connection — don’t fit pgwire without abusing it with session variables
and ad-hoc syntax. A pgwire compatibility layer for plain CRUD remains a possible
later addition; what an Arkeion server sells is precisely what pgwire cannot say.
Open-core, drawn at the repository line
The open-core boundary is drawn at the repo level, so the open library stays pure and the commercial server never has to touch it.
- The engine and protocol ship together and stay open. The wire protocol is hand-written — no serde — and reuses the engine’s own varint and value encoding.
- The client is a synchronous Rust SDK (
use_branch,execute,query,query_as_of,verify). Keeping it open is what makes the server adoptable. - The server,
arkeiond, is proprietary. It is thread-per-connection with no async runtime, which suits the single-writer engine and keeps the supply chain small. Offering it as a hosted service requires Syrakon’s prior approval.
A session is a view onto a branch
One TCP connection is one session, and a session is a view onto a branch
(main by default, switchable). The engine’s single writer serialises the
writes of every client; reads run against snapshots — including AS OF — in
parallel, and never block.
Two consequences follow from the single writer. The server’s write ceiling is the
writer’s ceiling, so group commit — amortising the per-commit fdatasync across
clients — is a planned optimisation. And because an open transaction holds the
write lock for its whole life, timeouts and cancellation are needed so one stuck
client can’t stall the rest.
On the wire
Framing is deliberately boring: a length-prefixed frame carrying a tagged payload, capped at 64 MiB so a bad frame can’t exhaust memory.
frame = [u32 LE length][payload]
payload = [u8 tag][fields...] # fields use the engine's varint + value codec
tag → message
Hello / Welcome handshake
UseBranch switch the session's branch
Execute → Affected a write; returns rows affected
Query{AS OF} → Rows a read, optionally against a past version
Verify → Audit cryptographic check; returns the chain hash
Error structured failure
Security
- Encryption in transit (TLS) complements the engine’s encryption at rest. The
first cut speaks plaintext on
localhost; TLS is on the near roadmap. - The connection layer is the home for auth, roles and per-branch permissions —
for example
mainread-only for some clients, a writable feature branch for others.
Status
The protocol, the client, and the server are in place: CRUD, branch isolation,
AS OF, verify, and diff/merge all work over a real socket. Next on the
line are multi-statement transactions (with a writer timeout), then TLS with auth
and per-branch permissions, and — optionally — a pgwire compatibility layer for
generic CRUD.