Skip to content

apomesh-state-store-postgres

The production durable-persistence adapter family. This crate is the Postgres side of the substrate’s state-store layer: the hexagonal adapters that sit behind the substrate’s store ports and back a cloud deployment. PostgresStateStore is the primary adapter — the durable event log, snapshots, and the memory tiers — and it ships alongside the HybridStateStore composition and a family of sibling Postgres adapters (catalog, registries, credentials, tokens, assets) the daemon constructs over one shared connection pool. Reach for this crate when a deployment needs durable persistence rather than the in-memory or SQLite adapters.

  • Layer: state stores — the deployment-persistence adapters behind the substrate’s store ports. See The event log for the event-log and checkpoint model these adapters durably back.
  • Depends on: apomesh-protocol (wire types decoded at the store boundary), apomesh-substrate (the store ports + domain types), and apomesh-state-store-redis (the cache HybridStateStore composes inward).
  • Consumed by: apomesh-orchestrator-bin (constructs the store and every sibling adapter at boot), apomesh-worker (a pool for asset streaming), and apomesh-reseal (sealing-key rotation).
  • The primary durable StateStorePostgresStateStore: the tenant-bound event log (append with a bounded position-conflict retry, read, poll-based stream, prune), CheckpointSource-tagged snapshots, working memory, the episodic / semantic / procedural memory tiers, and the side-effect log.
  • pgvector semantic memorysemantic_memory uses a halfvec + HNSW cosine index; retrieval is a linear blend of vector cosine and BM25 (ts_rank_cd over websearch_to_tsquery). The vector column’s dimension is provisioned at boot to the configured embedding provider’s embedding_dim() (ensure_embedding_dimension).
  • The production compositionHybridStateStore (in hybrid.rs): write-through over the durable Postgres adapter (authoritative) plus the apomesh-state-store-redis cache (hot working-memory reads and a best-effort event-log replay buffer).
  • Embedded schema migrations — a MIGRATIONS const embeds each migrations/*.sql via include_str!; run_migrations applies them transactionally and idempotently, tracked in _apomesh_migrations. The crate goes crate-direct on sqlx (no sqlx::migrate! macro) to avoid a SQLite-links collision — so the runner is inline.
  • At-rest sealingSecretSealer (ChaCha20-Poly1305, a fresh per-value nonce, apomesh-sealed:v1: tokens, key from APOMESH_SECRET_KEY) seals the secret-bearing fields of the credential and MCP adapters before INSERT so no cleartext lands in JSONB.
  • The sibling store family over one shared pool — the Postgres adapters for the agent catalog, the published-agent / strategy-config / published-skill registries, the mutable skill catalog, completed sessions, MCP servers, provider credentials, LLM config, provider profiles, runtime tokens, and assets.

It does not own the store ports. The StateStore, CredentialStore, TokenStore, AgentCatalog, AssetStore, and registry traits are defined in the substrate (apomesh-substrate-types / apomesh-substrate); the in-memory and SQLite adapters live in apomesh-substrate-state. This crate is only the Postgres adapter behind those ports.

Entry pointContract
PostgresStateStoreThe primary durable StateStore adapter — connect(url, pool_size), then the boot triad below.
run_migrations / ensure_embedding_dimensionIdempotent schema apply, then provision the vector column to the embedding dimension. Called once at boot.
HybridStateStorenew(postgres, redis_cache, ttl) — the write-through production stack.
SecretSealerseal / unseal for secret-bearing fields; refuses to start without a valid key.
PostgresProviderCredentialStoreThe sealed CredentialStore adapter — secrets sealed on upsert, unsealed on list.
PostgresAgentCatalogThe agent-manifest catalog (seed_shipped_manifests seeds the shipped defaults).
PostgresAgentRegistry / PostgresStrategyConfigRegistry / PostgresPublishedSkillRegistryThe versioned-immutable registry family — per-version immutability and adapter-internal AllowedTenants permits-gating.
PostgresCompletedSessionStoreThe keyset-paginated terminated-session index.
PostgresAssetStoreContent-addressed, chunked-row blob storage that streams rather than buffers.
DbPoolThe PgPool re-export the daemon captures once and shares across every sibling adapter.

The daemon selects a backend from the [statestore] config section (a closed StateStoreBackend enum: in-memory, sqlite, postgres, or hybrid):

[statestore]
working_memory_ttl_seconds = 86400
[statestore.backend]
kind = "hybrid"
postgres_url = "postgres://apomesh@localhost/apomesh"
redis_url = "redis://localhost:6379"
postgres_pool_size = 20

For the durable backends it connects, migrates, provisions the vector column, then captures the pool once and reuses it for every sibling store:

use std::{sync::Arc, time::Duration};
use apomesh_state_store_postgres::{HybridStateStore, PostgresStateStore};
use apomesh_state_store_redis::RedisCache;
let pg = PostgresStateStore::connect(&postgres_url, pool_size).await?;
pg.run_migrations().await?;
pg.ensure_embedding_dimension().await?;
// One pool, captured once and shared across the completed-session index,
// agent catalog, registries, and credential store.
let pool = pg.pool().clone();
// The production stack wraps that same durable adapter with the Redis
// hot cache (write-through).
let store = HybridStateStore::new(
Arc::new(pg),
Arc::new(RedisCache::connect(&redis_url).await?),
Duration::from_secs(working_memory_ttl_seconds),
);
  • Concepts: Sessions and events (the event log + checkpoints), Memory plane (the episodic / semantic / procedural tiers), and Credential plane (what SecretSealer protects at rest).
  • Operate: Local stack — the Compose stack that runs the pgvector reference image.
  • Contribute: Testing — the testcontainers-gated integration suite that boots Postgres + Redis per run.