Overview & architecture
Dodona is a gRPC-first application substrate where progressive delivery and provable data sovereignty are native primitives — able to run on top of the cloud you already have.
The problem
The parts of Kubernetes people actually fight with — service routing, releases, identity, traffic policy — are assembled from four leaky layers stacked on top of each other:
Service (L4 VIP) + kube-proxy/iptables + CoreDNS + bolt-on Istio/Envoy sidecars Each layer translates the layer below into something closer to what you wanted. The thing you actually wanted — "route this request to the right version of the right service, securely, and prove where the data went" — is an L7 concern, and the conventional stack only gets there by gluing a second control plane (a service mesh) onto the first, plus a flag SaaS in app code, plus a rollout operator driving the mesh through CRDs.
Dodona's bet: if identity and an L7 gRPC data plane are the substrate instead of add-ons, those layers collapse into one coherent thing — and progressive delivery and data sovereignty fall out of it in one place.
One brain, two skins, two drivers
┌─────────────────────────┐ ┌──────────────────────────┐
│ SKIN 1: native gRPC API │ │ SKIN 2: emulated K8s API │ ← front-ends
│ (new services) │ │ (legacy workloads · roadmap)│
└────────────┬────────────┘ └────────────┬─────────────┘
└───────────────┬────────────────┘
▼
┌────────────────────────────────────────────────┐
│ THE BRAIN (owned — the differentiator) │
│ discovery · identity · L7 routing │ ← one control plane
│ progressive-delivery & sovereignty policy │
└────────────────────────────────────────────────┘
▲
┌───────────────┴────────────────┐
┌────────────┴────────────┐ ┌────────────┴─────────────┐
│ DRIVER 1: k8s-driver │ │ DRIVER 2: cloud-driver │ ← back-ends
│ run on EKS/GKE (rented) │ │ run on EC2/GCE (roadmap) │
└─────────────────────────┘ └──────────────────────────┘ - Two skins (front-ends): a native gRPC API for new
services, and — on the roadmap — an
emulated Kubernetes API that hosts the real
kube-apiserverfor legacy workloads. Both funnel into one brain. - One brain (owned): endpoint registry, identity, L7 routing, and the progressive-delivery / sovereignty policy engine. The architectural invariant: there is exactly one control plane and one capacity view under both skins.
- Drivers (back-ends): Kubernetes and cloud/static discovery drivers already register endpoints into the brain. Live autoscaling and broader provider actuation are later driver-framework work.
The data plane: proxyless gRPC
The gRPC library itself is the data plane. In Rust this is
DonaChannel, a tower Service that any generated
typed gRPC client runs on; in Go it is a connection-level interceptor. Either
way, every call executes the same pipeline in your process:
1. context — request attributes plus authenticated mTLS/SPIFFE identity where present
2. constraint — hard: residency filters the eligible endpoint set; deny + audit
3. selection — soft: flag rules (sticky bucketing), else canary weights
4. balance — pick a ready endpoint of the chosen variant This is stronger than a sidecar, not just leaner: there is no proxy hop to pay for and no sidecar to bypass. Enforcement also runs in the serving process (a server-side interceptor), so even traffic that skips Dodona routing entirely is still policed — that is what makes sovereignty provable rather than configured.
Honest costs of proxyless: native coverage is gRPC/HTTP2; each SDK language is a maintenance commitment (Go and Rust exist and are held to a shared conformance contract); non-gRPC traffic goes through a proxy fallback driver. The current xDS adapter serves state-of-the-world ADS/CDS/EDS; LDS/RDS/delta export is still future work.
The control plane
The brain (donad) keeps an endpoint registry fed by
streaming leases — the registration stream is the
liveness signal, so endpoints vanish from the routing table the moment a
workload dies. Config fans out over per-service
WatchConfig streams: each client subscribes to exactly the
services it calls and receives full snapshots only for those. That
per-client scoping is the delta-xDS discipline that avoids the
config-blast-radius ceiling, applied from day one.
The SDK batch-reports call outcomes, flag exposures, and audit events
back to the brain. Outcomes feed rolling per-variant health windows; the
canary controller judges those
windows to step, promote, or roll back a rollout. Flags, ingress,
shared-service records, artifacts, releases, deployments, cells, and the
audit chain persist when donad --data-dir is set.
Multi-replica brain HA is still later store integration work.
What exists today
Implemented, tested, runnable, and reflected in the 2026-07-07 audit:
- Rust workspace (
rust/): 28 crates, including the brain, proxyless SDK, deployment pipeline, identity, sovereignty, store, xDS, agent, ingress, edge, auth, console, observe, drivers, scheduler, CLI, demo, e2e, and Directory relay/connector crates. - Deployment pipeline: artifacts, releases, deployment records, manual holds, rollout actions, scheduling-tag checks, and deployment mutation audit.
- SPIFFE and federation identity: token-gated SVIDs, scoped join tokens, node attestation, cells, bundles, revocation, and workload SVID grants, with documented verifier seams.
- Ingress, edge, auth, and console: public HTTP routing, route auth, Cloudflare DNS/cert reconciliation, a minimal auth helper, and operator dashboard/API/MCP surfaces.
- Observe: gRPC ingest/query, memory and ClickHouse stores, spool handling, service/log/metric/trace/error/Kubernetes query APIs, and an agent collect stream. Native OTLP receiver and browser explorers are not implemented yet.
- Go reference implementation (
phase0/): the original thesis proof and cross-language conformance peer. It does not have deployment, federation, or observe wrapper APIs.
Next steps
- Quickstart — run the five-scenario demo in Go or Rust.
- Concepts — flags & sticky bucketing, the canary state machine, residency & audit, endpoint leases.
- Control-plane API — the proto surface.