Skip to content

Use Postgres Store

Use this when you need durable, multi-instance persistence backed by PostgreSQL.

  • awaken-stores crate with the postgres feature enabled
  • A running PostgreSQL instance
  • sqlx runtime dependencies (tokio)
  1. Add the dependency.
[dependencies]
awaken-stores = { git = "https://github.com/AwakenWorks/awaken", features = ["postgres"] }
  1. Create a connection pool.
use sqlx::PgPool;
let pool = PgPool::connect("postgres://user:pass@localhost:5432/mydb").await?;
  1. Create a PostgresStore.
use std::sync::Arc;
use awaken::stores::PostgresStore;
let store = Arc::new(PostgresStore::new(pool));

This uses default table names for the runtime projections: awaken_threads, awaken_runs, awaken_messages, awaken_configs, and awaken_threads_state.

  1. Use a custom table prefix.
let store = Arc::new(PostgresStore::with_prefix(pool, "myapp"));

This creates tables named myapp_threads, myapp_runs, myapp_messages, myapp_configs, and myapp_threads_state.

  1. Wire it into the runtime.
use std::sync::Arc;
use awaken::contract::commit_coordinator::CommitCoordinator;
use awaken::AgentRuntimeBuilder;
use awaken::engine::GenaiExecutor;
use awaken::registry_spec::ModelSpec;
use awaken::stores::PgCommitCoordinator;
let coordinator =
Arc::new(PgCommitCoordinator::new(store.clone())?) as Arc<dyn CommitCoordinator>;
let runtime = AgentRuntimeBuilder::new()
.with_commit_coordinator(coordinator)
.with_agent_spec(spec)
.with_provider("anthropic", Arc::new(GenaiExecutor::new()))
.with_model(ModelSpec::new("claude-sonnet", "anthropic", "claude-sonnet-4-20250514"))
.build()?;
  1. Schema creation.

    Tables and indexes are auto-created on first access via ensure_schema(). The thread/run/message/config tables store JSONB payloads plus indexed columns needed for list and cursor queries. The store also installs schemas for event storage, protocol replay, outbox, checkpoint repair, and versioned registry state when those server control-plane stores are used.

  • runtime projections: threads, runs, messages, thread state
  • managed config: namespace/id config rows and notify channel
  • server control plane: events, replay, outbox, checkpoints, registry versions

No manual migration is required for initial setup.

After running the agent, query the database:

SELECT id, updated_at FROM awaken_threads;
SELECT id, updated_at FROM awaken_runs;

You should see rows corresponding to the threads and runs created during execution.

ErrorCauseFix
sqlx::Error connection refusedPostgreSQL is not running or the connection string is wrongVerify the DATABASE_URL and that the database is accepting connections
StorageError on first writeInsufficient database privilegesGrant CREATE TABLE and INSERT permissions to the database user
Table name collisionAnother application uses the same default table namesUse PostgresStore::with_prefix to namespace tables

crates/awaken-stores/src/postgres.rsPostgresStore implementation with schema auto-creation.

  • crates/awaken-stores/Cargo.tomlpostgres feature flag and sqlx dependency
  • crates/awaken-stores/src/postgres.rsPostgresStore
  • crates/awaken-stores/src/lib.rs — conditional re-export