-
Name Previous Value Current Value Priority
Normal
Major
-
Migrated from Linear KKN-197. Original: https://linear.app/kokonut/issue/KKN-197/distributed-replicas
-
Previous Value Current Value empty v1.1-hardening
-
-
-
Previous Value Current Value v1.1-hardening
backlog
-
Migrated from Linear KKN-197 (https://linear.app/kokonut/issue/KKN-197/distributed-replicas)
Based on your choices — geographic edge + data residency, sharded by location_id, and extend the current Compose stacks — the most suitable approach is a Federated Edge-Replica topology: each replica is a full, self-contained Kokonut stack deployed near a region/community, owning a disjoint set of locations, with a lightweight control plane for instance discovery/trust and eventual, aggregate-only cross-replica sync built on the existing federation layer. This reuses location_id partitioning and the "configurable container" precedent instead of introducing distributed-write consistency.
Below is the plan. (Per plan mode I've made no changes — this is a proposal.)
Recommended Architecture: Federated Edge Replicas
Principles
Phased Plan
Phase 0 — Instance identity & routing (foundation)
Phase 1 — Make a replica a parameterized, copyable unit
Phase 2 — Control plane: discovery, heartbeat, trust
Phase 3 — Cross-replica sync (eventual, aggregate/query)
Phase 4 — Routing & external surface
Phase 5 — Store-level HA within a replica (optional, per-replica)
Phase 6 — Observability, backup, DR
Recommended MVP slice (do this first)
Phase 0 + Phase 1 + minimal Phase 2: add instance_registry + location.home_instance_id, parameterize the Compose stack into a copyable unit, add provision-replica.sh, and a basic instances register/list/heartbeat CLI. This delivers "scale by standing up another self-contained replica that owns a set of locations," with sync added incrementally later.
Deliberately avoided: active-active multi-master sync, a Kubernetes migration, and per-tenant schema rewrites — the sharded-by-location model makes all three unnecessary for the stated goal.
Risks / open questions
Distributed Replicas Implementation Plan
Target Architecture
Use federated regional replicas, each running a complete Kokonut stack:
Core rules:
locationhas exactly onehome_instance_id.A new
platform_instanceregistry is preferable to overloadingfederation_node:federation_noderepresents data-sharing peers, whileplatform_instancerepresents infrastructure ownership and routing.Phase 0: Instance Identity and Location Routing
Objective
Introduce platform-instance identity and assign every location to a home replica without changing deployment behavior.
Schema
Add a new migration, using the next available migration number:
Suggested fields:
id UUID PRIMARY KEYinstance_code TEXT UNIQUEdisplay_name TEXTregion TEXTnode_url TEXTpublic_key TEXTtrust_levelstatus:provisioning,active,draining,suspended,offlinecapabilities JSONBlast_heartbeat_atcreated_at,updated_atExtend
locationwith:home_instance_id UUIDownership_statusownership_versionownership_changed_atownership_changed_byInitially allow
home_instance_idto be nullable for migration compatibility. Backfill all existing locations to the bootstrap instance, then add theNOT NULLconstraint.Add indexes:
Do not add
instance_idto every business table initially. The ownership relationship should be inherited throughlocation_id.Services
Add
services/instances/:registry.pyownership.pyheartbeat.pymodels.pycli.pyCore operations:
Add a bootstrap instance seed that is idempotent.
Gateway
Extend capability validation so capabilities may optionally include:
The gateway must reject a request when:
Tests
Add:
Completion Gate
Phase 0 is complete when:
location_id → home_instance_id.Phase 1: Parameterized, Copyable Compose Replica
Objective
Make the existing Compose stack deployable multiple times with different instance identity and storage.
Configuration
Add instance-level environment variables:
Keep database credentials and private keys instance-specific.
Add an instance environment template, for example:
Never include real secrets or private keys.
Compose Changes
Parameterize:
Preserve the existing two-network model:
databasesappsKeep PostgreSQL, ClickHouse, Directus, and Redis private.
Add an explicit replica label to services:
Provisioning
Add:
Provisioning should:
Do not make provisioning automatically assign locations. Ownership assignment must be explicit.
Seed Behavior
Update seed behavior so:
Tests
Add:
Completion Gate
Phase 1 is complete when two isolated Compose stacks can run simultaneously on separate hosts using:
Phase 2: Instance Registry, Discovery, Heartbeats, and Trust
Objective
Create a reliable control-plane protocol for replica membership and trust.
Registry Model
Implement instance lifecycle:
Only
activeinstances may receive writes or publish synchronization data.Use
platform_instanceas the authoritative infrastructure registry. Link a platform instance tofederation_nodeonly where it participates in data federation.Protocol
Add signed instance-to-instance messages with:
Message types:
heartbeatownership_manifestaggregate_sharequery_requestquery_responsesync_ackownership_transferUse replay protection:
Do not rely on the existing
node_public_keyfield alone without defining key rotation and trust semantics.API
Expose authenticated internal endpoints through the gateway or a dedicated internal service:
These routes must:
CLI
Add:
Tests
Add:
Completion Gate
Phase 2 is complete when:
Phase 3: Eventual Cross-Replica Synchronization
Objective
Exchange approved data between replicas without creating distributed transactions or leaking private data.
The current
federation_sharestores aggregate JSONB andfederation_querystores query state. Retain those concepts, but add a durable outbox and delivery protocol.Outbox Schema
Add:
Suggested fields:
id UUIDsource_instance_iddestination_instance_identity_typeentity_idlocation_idevent_typeaggregate_versionpayload JSONBpayload_hashidempotency_keystatus:pending,leased,delivered,failed,dead_letterattempt_countnext_attempt_atleased_untillast_errorcreated_atdelivered_atAdd:
to provide durable deduplication and inbound message tracking.
Data Classification
Define explicit synchronization classes:
| Class | Default behavior | | -- | -- | | Private operational records | Never replicated by default | | Verified public aggregates | Replicated | | Governance summaries | Replicated if consented | | Location metadata | Replicated selectively | | Raw sensor data | Kept local unless explicitly approved | | Evidence hashes/CIDs | Replicated | | Credentials/secrets | Never replicated | | Draft/agent records | Local unless explicitly requested |
The platform's existing governed lifecycle and privacy rules remain authoritative.
Aggregate Export
Create an export layer that produces approved, deterministic payloads:
Every export should include:
Do not replicate arbitrary table rows as the first implementation.
Delivery Engine
Extend
SyncEnginewith:Use PostgreSQL durable state for scheduler claims and leases, consistent with repository integrity requirements.
Query Federation
Extend
federation_queryto support:Queries must be allowlisted. Do not permit arbitrary SQL over the network.
Location Ownership Transfer
Implement a controlled transfer workflow:
The transfer must:
home_instance_id.Tests
Add:
Completion Gate
Phase 3 is complete when:
Phase 4: Global Routing and External API Surface
Objective
Route users and services to the correct home replica while preserving locality and fail-closed authorization.
Routing Model
Introduce a global routing layer that resolves:
Use a cached signed ownership manifest to avoid making every request depend on a live central database.
The routing layer should:
409/421-style ownership error when misrouted.Gateway Changes
Extend gateway route context with:
Add:
Do not expose database connections or internal service URLs.
Public Read Layer
For global reports:
For operational location views:
Caddy/Traefik
Use the current Caddy/Traefik deployment patterns for:
Do not make Caddy directly responsible for database ownership logic. Put ownership-aware routing in the gateway or dedicated routing service.
Tests
Add:
Completion Gate
Phase 4 is complete when:
Phase 5: Stateful High Availability Within Each Replica
Objective
Prevent a single database failure from taking down an entire regional replica.
This phase should be implemented per replica, not as cross-region multi-master replication.
PostgreSQL
Topology:
Implement:
Update connection configuration in
services/ingestion/base.pyand shared database helpers to support:target_session_attrs=read-writefor write connectionsKeep writes primary-only.
For analytics workloads, use a read-only connection pool/endpoint where safe. Do not route governance or lifecycle writes to read replicas.
PostgreSQL Failure Handling
Define explicit states:
Add operator commands:
Promotion should require an explicit operator or approved automation policy. Avoid split-brain.
ClickHouse
Start with one ClickHouse node per replica plus verified backups. Add replicated storage only when the operational SLO requires it.
For replicated ClickHouse:
remote_servers.ReplicatedMergeTreetables.Do not introduce ClickHouse replication before defining:
Redis
For Redis:
HA Tests
Add:
Completion Gate
Phase 5 is complete when each production replica has:
Phase 6: Observability, Backup, Disaster Recovery, and Operations
Objective
Make the distributed system operable at scale, with visibility into ownership, sync, routing, storage, and recovery.
Metrics
Add metrics for:
Instance health
Routing
Synchronization
Database HA
Data governance
Use the repository's existing logging conventions and health checks rather than adding unstructured
print()calls.Health Endpoints
Extend health reporting with:
Health responses should distinguish:
A replica with stale ownership or failed sync may remain available for local reads but must not automatically accept new ownership or transfer operations.
Backups
Each replica needs:
Never back up secrets in plaintext or publish private evidence payloads.
Disaster Recovery
Document and test:
Operator Tooling
Add:
All replay, disposal, failover, and ownership changes should require an explicit operator identity and produce an audit record.
Dashboards and Alerts
Create dashboards for:
Alert on:
Completion Gate
Phase 6 is complete when:
Cross-Phase Delivery Order
Use separate branches and PRs, following the repository workflow:
feat/distributed-instance-identityfeat/distributed-compose-provisioningfeat/distributed-instance-registryfeat/distributed-replica-syncfeat/distributed-global-routingfeat/distributed-replica-hafeat/distributed-operationsEach phase should merge only after its migration, focused tests, security review, and rollback procedure are complete.
Phases can be partially parallelized:
Recommended Initial Milestones
Milestone A: Two isolated replicas
Milestone B: Trusted federation
Milestone C: Aggregate synchronization
Milestone D: Global access
Milestone E: Production resilience
Milestone F: Operable federation
Key Decisions to Preserve