A data-center swarm on PostgreSQL.
Several racks of ai-memory daemons, each built with sal-postgres and started with a postgres:// store URL, keep their memories in an operator-run PostgreSQL 18 deployment with pgvector and, when installed, Apache AGE. The daemons federate across racks with signed W-of-N quorum writes. Agents never connect to PostgreSQL: every request terminates at a daemon.
Daemons in every rack, one PostgreSQL deployment underneath.
Each host runs its agents, one daemon and one same-host wake hub. The daemons are first-class federation peers across racks. The PostgreSQL primary, its streaming replicas and the connection pooler are run by you: ai-memory does not know the replication topology and treats its configured --store-url as authoritative.
What is ai-memory and what is yours. The daemons, the federation mesh and the wake hubs are ai-memory; the pooler, primary and replicas are PostgreSQL, configured per the enterprise deployment guide. MCP over stdio is SQLite-only, so agents on this tier use HTTPS. Sources: src/daemon_runtime.rs (--store-url), src/store/postgres_schema.sql, src/store/postgres.rs, src/federation/sync.rs, src/wake_hub/server.rs.
A route gate that fails closed.
On PostgreSQL the daemon puts postgres_route_gate in front of every handler. It checks the method and path against an explicit allowlist: a supported path reaches the PostgreSQL storage layer, a registered path that is not yet supported answers a uniform 501 NOT IMPLEMENTED, and an unregistered path answers 404. No request ever reads or writes the wrong database.
Graph walks. At boot the PostgreSQL store checks whether the AGE extension is installed; with it, knowledge-graph walks use a Cypher projection, without it they fall back to a recursive CTE. memory_links is the source of truth either way. Sources: src/handlers/postgres_gate.rs, src/store/postgres.rs; guide: graph backend fallback.
One write, one recall.
Commit in PostgreSQL, then replicate
- An agent in rack A sends
POST /api/v1/memorieswith itsX-Agent-Idto the daemon on its host. - The route gate admits the path; identity and the namespace governance gate run as on every tier.
- The row commits in PostgreSQL (MVCC, so concurrent writers from other daemons do not serialize on a file lock).
- The daemon signs the body and fans it out to its
--quorum-peersin the other racks; W acknowledgements in time acknowledge the write, a miss answers202withquorum_met:falseand the row stays committed. - PostgreSQL streams the WAL to the replicas: that is your database, not ai-memory's replication.
Keyword, vector and graph in one database
- An agent in rack B sends
POST /api/v1/recallto its local daemon. - Scope visibility filters what the caller may see, from its namespace position.
- Keyword search runs on
tsvector, semantic search on a pgvector column, graph walks on AGE or the CTE fallback. - The result returns over HTTPS; nothing about the recall path is exposed as a PostgreSQL connection to the agent.
One daemon per host, every flag real.
Build with the sal-postgres feature. --store-url and --db are mutually exclusive; keep the URL out of argv with AI_MEMORY_STORE_URL_FILE. A non-loopback bind also needs api_key set in config.toml, and every listener is TLS. serve and curator run against PostgreSQL; the tenant-facing CLI read/write verbs and MCP over stdio are SQLite-only; the admin verbs schema-init, keys, reown, verify-audit-trail, agents bind-api-key, identity hub-cache and doctor take a per-run --store-url target.
# ai-memory, on each host (rack A host 1 shown)
cargo build --release --features sal-postgres
AI_MEMORY_STORE_URL_FILE=/etc/ai-memory/store-url \
ai-memory serve \
--host 0.0.0.0 --port 9077 \
--tls-cert /etc/ai-memory/tls.crt --tls-key /etc/ai-memory/tls.key \
--mtls-allowlist /etc/ai-memory/mtls-allow.txt \
--quorum-writes 2 \
--quorum-peers https://rack-b-1:9077,https://rack-c-1:9077 \
--quorum-timeout-ms 2000 \
--quorum-client-cert /etc/ai-memory/fed.crt --quorum-client-key /etc/ai-memory/fed.key \
--quorum-ca-cert /etc/ai-memory/fed-ca.crt \
--catchup-interval-secs 30
# the same host's wake plane (Unix socket, same host only)
ai-memory wake-hub --socket /run/ai-memory-hub/wake-hub.sock \
--hub-id rack-a-1 --allowlist /run/ai-memory-hub/hub-allow.json
# health, locally and across the fleet; doctor --json reads the local SQLite --db
# unless AI_MEMORY_STORE_URL / AI_MEMORY_STORE_URL_FILE points it at PostgreSQL
AI_MEMORY_STORE_URL_FILE=/etc/ai-memory/store-url ai-memory doctor --json
ai-memory doctor --remote https://rack-b-1:9077 --api-key-file /etc/ai-memory/api.key
# PostgreSQL side: OPERATOR configuration, not ai-memory
# primary + streaming replicas, a pooler in transaction mode,
# pg_basebackup + WAL archive for backups, TLS (sslmode=verify-full),
# a role allowed to create the vector extension (and age, optionally)
Flags: src/daemon_runtime.rs (ServeArgs, DoctorCliArgs), src/cli/wake_hub.rs. Enrol each peer's transport certificate pin and Ed25519 signing key before the first push: see federation. ai-memory backup refuses non-SQLite stores, so PostgreSQL backups are yours.
Governance, wake and attestation at T4.
Same gate, now on PostgreSQL
Namespace standards, Allow / Deny / Pending decisions and the pending-action queue are enforced on PostgreSQL. The rule inspection API (memory_rule_list, memory_check_agent_action) is in the fail-closed set; enforcement itself is not.
One hub per host
A notify commits the inbox row in PostgreSQL, then wakes the host's hub. A recipient on another host learns of the row through federation, and its daemon publishes a local wake only for a fresh apply. Clients keep a backstop poll of at most a minute.
Signed, enrolled, scoped
Cross-rack pushes carry an Ed25519 X-Memory-Sig bound to an X-Memory-Nonce; receivers refuse unsigned, replayed and unenrolled pushes and check the sender's namespace scope.
Operator-attested
The enterprise posture check verifies the TLS store URL and requires an explicit operator attestation (AI_MEMORY_PG_AT_REST_ATTESTED) that volume encryption is on. It does not probe the disk; SQLCipher and application content encryption are separate controls.
Where T4 stops.
| Limit | What it means | Where it is documented |
|---|---|---|
| Daemon is the access path | No direct-to-PostgreSQL agent protocol; the daemons stay the throughput bottleneck. Add daemons, not database clients. | limits §5 |
| Fail-closed routes | Paths outside the PostgreSQL allowlist answer 501 on this tier (for example the Agent Skills surface and /api/v1/share). | README · backend parity |
| MCP stdio | SQLite-only. Agents on the PostgreSQL tier use HTTPS. | src/mcp/mod.rs |
| No CDC | No logical replication, publication or change stream is offered by ai-memory; observe changes through hooks and webhook subscriptions. | limits §7 |
| Replication is yours | Streaming replicas, failover and pooling are PostgreSQL operations; ai-memory follows its store URL. | enterprise deployment §5 |
| Eventual graph invalidation | A knowledge-graph invalidation reaches other peers asynchronously. | limits §13 |
Read the code.
src/handlers/postgres_gate.rs· route gate, allowlistsrc/store/postgres.rs· store, AGE detectionsrc/store/postgres_schema.sql· pgvector, tsvector
src/replication.rs· W-of-N quorumsrc/handlers/parity.rs· the 202 contractsrc/federation/signing.rs· signatures, nonces
src/daemon_runtime.rs· serve flagssrc/enterprise_federation_posture.rs· posture checksrc/wake_hub/server.rs· wake hub