Skip to content
ai-memory / architectures / T3
Menu
GitHub
Tier 3 · ships in v1.0.0

A cluster that agrees enough, and never loses a write.

Several ai-memory daemons in one rack or data center replicate every HTTPS write over mutual TLS with Ed25519-signed pushes. A write commits locally first, then waits for a W-of-N quorum; a miss is answered with 202 and the row stays safe. Peers that were away catch up by pulling, erasures travel through a durable outbox, and a replicated message wakes its recipient on the receiving host.

W-of-N quorum writes mTLS fingerprint allowlist X-Memory-Sig · nonce · enrolled keys 202 quorum_met:false /sync/since catch-up
Architecture

Three peers, one signed mesh.

Each peer is a full ai-memory serve with its own store and its own wake hub. With --quorum-writes W and a --quorum-peers list, every HTTPS write fans out to every peer and is acknowledged once the local commit plus W−1 peer acknowledgements land inside --quorum-timeout-ms.

signed pushacknowledgement · wake
Tier 3: a federated cluster of three daemonsThree ai-memory daemons in one rack or data center replicate every HTTPS write over mutual TLS with Ed25519-signed pushes. A write commits locally and is acknowledged once the local commit plus W minus one peer acknowledgements land within the quorum timeout; otherwise the answer is 202 with quorum_met false and durability local. Each host keeps its own wake hub. ONE RACK · ONE DATA CENTERmTLS allowlist · X-Memory-Sig · nonce · enrolled peer keysagent → peer A agent → peer B peer A · ai-memory servestore: SQLite, or PostgreSQL + AGEreceive: verify sig · attest · applyquorum: local commit + W−1 ackswake-hub on this host peer B · ai-memory servestore: SQLite, or PostgreSQL + AGEreceive: verify sig · attest · applyquorum: local commit + W−1 ackswake-hub on this host peer C · ai-memory servestore: SQLite, or PostgreSQL + AGEreceive: verify sig · attest · applyquorum: local commit + W−1 ackswake-hub on this host signed /sync/pushackpushpushAcknowledged when local commit + (W−1) peer acks land inside --quorum-timeout-ms; otherwise 202 Accepted, quorum_met:false, durability:"local".

The 202 contract. On a quorum miss the local row is already durable and is never rolled back, so the daemon answers 202 Accepted with {quorum_met:false, acks, needed, reason, durability:"local"} and queues the push for redelivery, never a 5xx. Sources: src/replication.rs, src/federation/sync.rs, src/federation/quorum.rs, src/handlers/parity.rs, src/federation/signing.rs, src/federation/peer_attestation.rs.

Failure, recovery, erasure

Partitions cost latency, not data.

A peer that misses a push gets it later, twice over: the push dead-letter queue replays it, and the peer's own catch-up loop pulls everything it missed with GET /api/v1/sync/since. When the row that arrives is a message, the receiving node publishes a local wake only if the apply actually moved the row forward, so replays never wake anybody.

Tier 3: partition, recovery and erasurePeer C is partitioned. A write on peer A still meets quorum with peer B; the push to C lands in the push dead-letter queue. When C rejoins it pulls missed rows with sync since on its catch-up interval and the queue replays. A freshly applied inbox row on C publishes a local wake through applied_wake. A forget on A goes through the durable erasure outbox to every peer. PARTITION AND RECOVERY01C partitionedA and B keep serving 02write on AA + B ack: quorum met 03push to C failskept in the push DLQ 04C rejoinscatch-up pull loop 05converged/sync/since + replay A MESSAGE ARRIVES ON C01notify on Ainbox row committed 02replicatedsigned push or pull 03apply on Cnewer-wins merge 04applied_wakefresh apply only 05wake on CC's hub, same host ERASURE FROM MCP OR CLI (an HTTPS DELETE broadcasts through the quorum directly)01forget on Avia MCP or the CLI 02local erasealways succeeds 03erasure outboxdurable, network-free 04daemon drainsfederation worker 05peers deletereplicas converge

Sources: src/federation/push_dlq.rs, src/federation/receive.rs (catch-up loop), src/federation/applied_wake.rs, src/federation/erasure_outbox.rs, src/handlers/federation_receive.rs.

Walkthrough

One write, one recall.

  1. Write on peer A. The row commits on A. A signs the canonical body (X-Memory-Sig) and pushes it over mutual TLS to B and C.
  2. Receive on B. B checks the client certificate fingerprint, the signature against A's enrolled Ed25519 key, the nonce, and that A may write the namespace it claims; then it applies the row and acknowledges.
  3. Quorum. With --quorum-writes 2, A's commit plus B's acknowledgement meet quorum and the client gets its success response. C, if slow, gets the row from the DLQ replay or its next catch-up pull.
  4. Recall on C. Recall is local to the peer that serves it: C answers from its own store. Immediately after a write, a recall on another peer can be a catch-up interval behind; read from the writing peer when you need the newest row.
Deployment recipe

Three peers in one rack.

# Each peer: an Ed25519 identity, and every other peer's public key enrolled
ai-memory identity generate --agent-id dc1/rack4/peer-a
ai-memory identity import --agent-id dc1/rack4/peer-b --pub peer-b.pub
ai-memory identity import --agent-id dc1/rack4/peer-c --pub peer-c.pub

# Each peer: TLS, the mTLS fingerprint allowlist, quorum fan-out and catch-up
# (a non-loopback bind also requires api_key in config.toml)
ai-memory --db /var/lib/ai-memory/ai-memory.db serve \
  --host 0.0.0.0 --port 9077 \
  --tls-cert /etc/ai-memory/peer-a.crt --tls-key /etc/ai-memory/peer-a.key \
  --mtls-allowlist /etc/ai-memory/peer-fingerprints.allow \
  --federation-identity dc1/rack4/peer-a \
  --quorum-writes 2 \
  --quorum-peers https://peer-b.dc1:9077,https://peer-c.dc1:9077 \
  --quorum-timeout-ms 2000 \
  --quorum-client-cert /etc/ai-memory/peer-a.crt --quorum-client-key /etc/ai-memory/peer-a.key \
  --quorum-ca-cert /etc/ai-memory/ca.crt \
  --catchup-interval-secs 30

Flags verified against src/daemon_runtime.rs (ServeArgs) and src/cli/identity.rs. Peer attestation JSON, enrolment posture and rotation are in the federation guide. Hub-spoke alternative: one PostgreSQL + Apache AGE hub daemon with spokes that push through /sync/push and pull through /sync/since, as described in enterprise deployment §4.2.

Wiring

Governance, wake plane and attestation at Tier 3.

Governance

Replicated decisions

Namespace standards, pending actions and pending decisions replicate through the same quorum fan-out, so an approval on one peer resolves the action everywhere (src/federation/sync.rs).

Wake plane

Local hubs, federated rows

Hubs never bridge hosts. A message crosses the cluster as a replicated inbox row, and applied_wake on the receiving peer turns a fresh apply into a local wake.

Attestation

Three layers

The mTLS allowlist authenticates the transport, the signature and nonce authenticate the push, and peer attestation checks the claimed sender and its namespace scope on /sync/push and /sync/since.

Honest limits

When Tier 3 stops fitting.

DimensionTier 3 behaviourMove up when
ConsistencyQuorum writes plus catch-up; no Raft or Paxos, no gossip discovery. Peers are listed explicitly.Always true; size quorum for the failures you must survive.
Graph invalidationKnowledge-graph invalidations reach other peers asynchronously.Read from the writing peer when you need the result immediately.
SurfacesHTTPS writes fan out. MCP-over-stdio writes join the quorum only when mcp_federation_forward_url points the MCP server at the local daemon; writes that skip the quorum (MCP without the forward URL, CLI) reach peers through the catch-up pull from /sync/since, every 30 s by default (a peer receives only rows in namespaces its attestation allowlist grants (deny by default) that are visible to its identity; scope=private rows stay on the node unless marked federation_share:true or the operator sets AI_MEMORY_FED_SYNC_TRUST_PEER=1). MCP and CLI erasures reach peers through the erasure outbox drained by the daemon.Set the forward URL, or route agents that need replication through HTTPS.
Per-peer storeSQLite peers each keep one writer at a time and an in-process vector index.Write load or corpus size grows: PostgreSQL tier.
Wake reachWakes are per host; the cross-host leg is federation, and the poll remains the guarantee.No change needed at larger tiers.

Reasoning for each: architectural limits and federation.