Local Postgres for AI agents, same as prod.
Declare a database once in a2a.yaml. Run `a2a chat` and get a real local Postgres — postgres:16-alpine over Docker Compose, pgvector available, DATABASE_URL injected. Deploy, and the same declaration provisions a managed Neon Postgres per agent with the same connection contract. One declaration, a real database in development and production, no SQLite-in-dev mismatch to debug later.
declare once · real Postgres in dev · same engine in prod
Dev used SQLite. Prod used Postgres. The bug lived in the gap.
The path of least resistance is a fake database in development — SQLite or a mock — because standing up a real Postgres locally feels like too much setup. Then production runs Postgres, and now you're testing against one engine and shipping to another. Migrations that pass locally fail live, types and transaction semantics differ, and pgvector — the extension your agent memory depends on — simply isn't there in the stand-in. The gap between dev and prod becomes a category of bug you only find after deploy.
Declare the database once; get a real Postgres on both sides.
A single `resources.databases` block in a2a.yaml is the whole contract. Locally, `a2a chat` provisions a real postgres:16-alpine over Docker Compose with a persistent volume and pgvector; in production the same declaration provisions a managed Neon Postgres per agent. Same engine, same DATABASE_URL, same connection contract — dev↔prod parity by construction.
Declare the database once
Add `resources.databases` to a2a.yaml — a name, provider neon, engine postgres, and an env like `url: DATABASE_URL`. That single declaration is the contract for both local development and production. There is no second config file for dev.
A real local Postgres
Run `a2a chat` and the database is provisioned locally via Docker Compose as postgres:16-alpine with a persistent volume. Your agent connects at postgresql://a2a:a2a@postgres:5432/<db>, with DATABASE_URL injected. You develop against Postgres, not a stand-in.
The same engine in prod
In production the exact same declaration provisions a managed Neon Postgres per agent. Same engine, same connection contract, same DATABASE_URL — so what you test locally is the database you ship to. Dev and prod stop drifting apart.
pgvector on both sides
The local Postgres has pgvector available, and so does the managed production database. Embeddings and semantic memory behave the same in `a2a chat` as they do live — you don't discover a missing extension after deploy.
One isolated DB per agent
Each agent gets its own database, locally and in production — an isolation and audit boundary, not a shared cluster with a tenant column. Your local dev store mirrors the per-agent boundary you run in prod.
Persistent local state
The local Postgres volume persists across `a2a chat` sessions, so migrations, seed data, and rows you wrote last run are still there. It behaves like a database you'd keep, not a scratch buffer wiped on restart.
Mismatched dev/prod databases vs. one declaration, real Postgres both sides.
Frequently asked.
How do I get a local Postgres for my AI agent?
Declare a database in a2a.yaml under `resources.databases` — a name, provider neon, engine postgres, and an env such as `url: DATABASE_URL`. Then run `a2a chat`, and the CLI provisions a local Postgres via Docker Compose (postgres:16-alpine with a persistent volume) at postgresql://a2a:a2a@postgres:5432/<db>, injecting DATABASE_URL into your agent. You develop against a real Postgres with no separate local setup.
Is the local development database the same as production?
It's the same engine and the same connection contract. Locally, `a2a chat` gives you postgres:16-alpine over Docker Compose; in production the identical a2a.yaml declaration provisions a managed Neon Postgres per agent. Same Postgres engine, same DATABASE_URL, same pgvector — so you get dev↔prod parity instead of a database that behaves one way in testing and another when live. The production side is covered in detail on the managed Postgres for AI agents page.
Why not just use SQLite in dev and Postgres in prod?
That's the mismatch this design exists to avoid. SQLite-in-dev, Postgres-in-prod means you test against one engine and ship to another, so migrations, types, transaction semantics, and extensions like pgvector can all behave differently in production than they did on your machine. Declaring the database once and running a real Postgres locally means the database you test is the database you deploy.
Does the local Postgres support pgvector for agent memory?
Yes. pgvector is available in the local Postgres that `a2a chat` provisions, and it's also present in the managed production database. That means embeddings, semantic memory, and vector retrieval behave the same in local development as they do in production — you won't build against a missing extension and find out after deploy.
Does my local data persist between `a2a chat` sessions?
Yes. The local Postgres runs on a persistent Docker volume, so migrations, seed data, and rows written in a previous session are still there when you start the next one. Each agent also gets its own isolated database locally, mirroring the per-agent isolation boundary you run in production, so your dev environment reflects the real shape of prod.
Related guides.
All guides live in the guides index.
One declaration. A real Postgres in dev and in prod.
a2a cloud deploys any agent — LangGraph, OpenAI Agents SDK, CrewAI, or custom — from a single a2a.yaml. Declare a database and you get a real local Postgres for `a2a chat` and the same managed Neon Postgres per agent in production, with pgvector on both sides. The managed production database, an MCP server, an API, a frontend, and an Ed25519-signed receipt per run come with it. No dev/prod database mismatch to debug after you ship.