KoutenDB Protocol / Compatibility Policy
KoutenDB Protocol / Compatibility Policy
This is the canonical compatibility note for KoutenDB’s current technical preview.
Scope
KoutenDB currently exposes two external contracts:
- C ABI:
KOUTEN_ABI_VERSION - TCP wire protocol:
WIREVER
Both are intentionally small. They are stable enough for local drivers and smoke tests, but KoutenDB does not yet claim long-term production compatibility across arbitrary mixed-version clusters.
Additive C ABI functions may retain the current ABI version when existing struct layouts, calling conventions, and symbol behavior do not change. The v0.12 disk-backed open, CRUD completion, bounded-maintenance, and generation- checkpoint JSON functions follow this rule, preserving ABI v2 for already- published wrappers.
Wire Protocol
The wire protocol is a KoutenDB-specific text-header protocol with length-prefixed payloads. It is easy to inspect and fuzz, but compatibility must be managed explicitly as commands grow.
Rules:
- Clients should check
WIREVERbefore assuming command compatibility. - Minor command additions may preserve the same version only when old clients can safely ignore them.
- Any incompatible frame, payload, numeric, or response change must bump
WireProtocolVersion. - Drivers should prefer public named-ring commands such as
PUTR,GETID,QRYID, andBGETinstead of constructing placement metadata themselves. FPUT,FPUTR,APPLYTX,TRF,TRFD, andUAPPLYare internal replication/apply commands. They require areplicatororadminidentity and are not application-driver CRUD APIs. Topology-fenced migration remains admin-only.CODECSreports the payload format identifiers accepted by the node.- Oversized
RETRIEVEwork is rejected with the existing stable error path (ERR bad-request). The response shape of successfulRHITframes is not changed by the query-cost guard.
Ownership redirects may append the calculated owner node to FWD responses.
The field is additive: older clients may ignore it, while current clients use
it to redirect directly instead of probing every node.
TOPOLOGY reports the physical placement epoch, node count, and virtual arcs
per node. Current clients use this response to reconstruct the same deterministic
virtual-arc table as the server. Cluster connections fail closed if this
metadata is unavailable or disagrees with the configured peer count; silently
falling back to legacy equal arcs would risk misrouting writes. Point reads are served only by the stable
physical ring owner. During topology migration, a source retains its copy until
the destination has applied the versioned transfer. Internal transfer frames
also carry an optional placement fence (epoch, node count, and virtual-arc
density), which the destination validates immediately before applying the
mutation. Clients follow at most two explicit owner redirects and never perform
all-node fan-out.
Ring-scoped RETRIEVE follows the same stable placement table and is sent only
to the selected ring’s physical owner. On the server, it walks the durable
ring index rather than filtering a whole-node record scan after the fact.
Global retrieval intentionally remains an all-node operation. The additive
METRICS counters retrievePhysicalVisited and retrieveCandidatesScored
make the difference observable without changing the successful RHIT frame.
Draining nodes reject retrieval after consuming the declared vector body, so
topology migration cannot turn an incomplete owner copy into a silent empty
result or corrupt the next frame on a persistent connection.
ACTIVATION is an admin-only local readiness report:
ACTIVATION READY|ACTIVE|BLOCKED <epoch> <nodes> <virtualArcs> <migrationPending>
resume clients compare this response across every configured peer before
requesting activation. Each server repeats peer topology/readiness checks before
clearing its persistent drain marker.
Coordinator redundancy adds commands without changing existing frame shapes:
COORDINATOR
TXMIRROR <coordinatorEpoch> <coordinatorNode> <txid> <opCount>
TXMIRRORAPPLIED <coordinatorEpoch> <coordinatorNode> <txid>
APPLYTXF <txid> <coordinatorEpoch> <coordinatorNode> ...
COORDPROMOTE <epoch> <coordinatorNode> <replicaNode>
COORDRESUME <epoch>
APPLYTX remains readable for legacy single-coordinator clusters. Redundant or
promoted coordinators use APPLYTXF; a destination rejects mismatched epochs or
coordinator node IDs. TXBEGIN, reserve, and commit return the current COORD
assignment outside the active primary. Status and landing reads are accepted by
the primary or standby and return COORD elsewhere. Current clients discover
the highest non-conflicting reachable assignment.
Topology-fenced TRF / TRFD frames may append MIGRATION. A drained server
accepts that path only for an admin-authenticated request with an exact topology
fence. Ordinary transfer frames and writer-role attempts remain rejected while
drained.
Scale-in uses admin-only operator commands rather than exposing migration primitives as normal driver CRUD:
MIGMETAapplies topology-fenced ring/galaxy/stellar/forwarder metadata;MIGVERIFYcompares a record or tombstone mutation version without changing target state;MIGMETAVERIFYcompares topology-fenced metadata without changing target state.
Body-carrying migration commands drain their declared body before returning a
topology error, preserving the next frame boundary on a persistent connection.
These commands are used by kouten scale-in-*; application drivers should not
use them directly.
Mutation Ordering
Particle and logical-delete transfer frames carry an optional hybrid logical mutation version:
<physicalMicros> <logical> <origin>
The tuple is compared lexicographically at the destination. A destination
rejects duplicate or older values, and a durable tombstone rejects a delayed
value that predates the delete. TRF appends the version after the codec;
TRFD transfers a logical-delete tombstone without a payload. Existing TRF
frames without these fields remain readable and derive a compatibility version
from tWrite.
Mixed-version rolling upgrades preserve old value transfers, but logical delete
convergence requires every receiving node to understand TRFD. An older node
rejects that unknown command; the upgraded source retains the tombstone and
retries instead of acknowledging or pruning it. Upgrade all cluster nodes
before relying on cross-node delete convergence.
Physical source eviction is deliberately separate from logical deletion.
Moving an acknowledged source copy writes a physical D record; application
deletion writes a versioned logical L tombstone. This prevents a normal
handoff departure from deleting the accepted destination value.
Tombstones survive WAL replay, compaction, backup, and restore. Delete
propagation is explicit and bounded by the configured peer count; it no longer
depends on a logical orbit carrying the marker through every node. Once every
configured peer ID has durably applied the same delete version, the completed
acknowledgement set is sent to every guard copy. Reclamation waits for that
fanout and the bounded stale-transfer drain window. Final reclamation writes
LG, so a restart cannot restore the marker after it was safely collected.
This is deliberately not a time-only tombstone TTL. Reclamation remains fail-closed while any configured peer is missing. Handoff workers also verify the destination’s placement epoch and topology before transferring a record. A tombstone that names a node outside the configured peer set is rejected rather than guessed through. Restoring an arbitrarily old node image after reclamation is also outside the direct-restart contract: operators must restore from a current recovery snapshot and complete catch-up before the node may serve or hand off data.
Payload Codec Metadata
PUT, PUTR, transaction apply, and handoff frames may append one codec name:
raw, json, nif, or bif. Clients that need response metadata first send
CODECMETA ON; negotiated VAL, ITEM, and HIT response headers then append
the stored codec where applicable. Clients that do not negotiate retain the
original response shape. Missing metadata is interpreted as raw for
compatibility with existing WAL records and drivers.
NIF/BIF bytes are opaque to KoutenDB core. The core preserves them across WAL
replay, cluster transfer, and retrieval but does not bundle a NIF/BIF encoder
or decoder. Use the optional
koutendb-nif adapter when an
application needs NIF text / BIF byte conversion. See
Payload Codecs.
Vector Byte Order
TCP wire vector bytes are canonical little-endian IEEE-754 float32 values.
This is now encoded and decoded explicitly in src/kouten/wire.nim; native wire
drivers must follow the same byte order.
The C ABI is different: C ABI calls accept normal host-native float arrays
inside the same process. The ABI boundary does not serialize those floats onto
the network directly.
WAL / Snapshot Compatibility
The internal WAL is not the long-term external migration format before v1.0.
New WAL files start with !KOUTENDB-WAL 2 and store each logical record behind
a length + CRC32 wrapper. This lets KoutenDB reject corrupted versioned records
instead of silently treating shifted payload bytes as later headers.
Legacy pre-v1.0 WAL records remain readable for migration and tests, but new
writes and compacted snapshots use the versioned format. For portable,
human-readable migration across releases, use kouten dump and
kouten import-jsonl rather than copying or editing WAL internals directly.
See Data Migration for the supported JSONL boundary.
The repository keeps immutable v0.10.1 and v0.11.0 stores under
tests/fixtures/. The upgrade matrix verifies their WAL replay and physical
segment migration with the current code, then verifies JSONL and checkpoint
recovery paths. These fixtures are a tested pre-v1 bridge for those releases;
they do not turn the internal WAL into a permanent external file format.
Generation checkpoints are versioned separately as
koutendb-checkpoint-v1. They are immutable restore artifacts that bind one
compact WAL to its ring segment/index files through a checksum inventory and a
manifest completion marker. They are not the pre-v1 portable migration format:
restore them with the same compatible KoutenDB release line, and use JSONL dump
and import when crossing an unsupported storage-format boundary.
Production Readiness Boundaries
KoutenDB has username/password/secret-key auth, ring-prefix authorization, simple RBAC, and deterministic wire fuzz smoke tests. For enterprise production claims, the remaining gaps are still material:
- certificate issuance, rotation, and expiry monitoring for TLS deployments;
- richer role policy and audit logs;
- automatic coordinator health policy and promotion orchestration;
- mixed-version live wire/driver tests and a documented rolling-upgrade policy.
Use TLS on untrusted networks and monitor coordinator, certificate, audit, and mixed-version boundaries according to the deployment risk.
Planner Boundary
The default retrieval planner is deterministic heuristic ranking. This is deliberate: it keeps the DB predictable and avoids embedding a model optimizer in the core. KoutenDB’s strongest current evidence is measured working-set and token reduction under documented synthetic workloads. Broader production claims must come from larger real-corpus benchmarks and planner improvements.