# Conversation store backends

All server-side backends require `VITE_FEATURE_CONVERSATION_DB=true` set at **build time** (before `bun run build`; this is a `VITE_*` build-time variable). Set `CONVERSATION_STORE_BACKEND` at runtime to force a specific backend, or leave it unset to auto-select.

## Platform recommendation

| Platform | Recommended store | Why |
|---|---|---|
| Cloudflare Workers | `d1` | Managed SQL, easy to inspect/migrate/export |
| Docker / self-hosted | `postgres` | Reuse existing infrastructure |
| Kubernetes | `postgres` | Standard managed database pattern |
| Any platform | `agentstate` | Cloud-hosted, no infrastructure to manage |
| Local development | `memory` | No setup; data is ephemeral |

## Auto-selection order

When `CONVERSATION_STORE_BACKEND` is not set, the server picks the first available backend:

1. **AgentState** — when `AGENTSTATE_API_KEY` is set and `CONVERSATION_STORE_BACKEND` is not explicitly `d1`, `postgres`, or `memory`.
2. **Cloudflare D1** — when the `CONVERSATIONS_D1` binding is present (Cloudflare Workers only).
3. **Postgres** — when `DATABASE_URL` is set.
4. **Memory** — fallback in development/CI.

## AgentState

Cloud-hosted conversation store. Works on all platforms. Requires an `as_live_` prefixed key.

```bash
AGENTSTATE_API_KEY=as_live_xxx
## AGENTSTATE_BASE_URL=https://agentstate.app/api   # optional override
## AGENTSTATE_AI_ENRICH=true                        # optional AI title enrichment
## CONVERSATION_STORE_BACKEND=agentstate             # optional — auto-selected when key is present
```

## Cloudflare D1

Cloudflare-only. Requires a provisioned D1 database and a Worker binding.

```bash
CONVERSATION_STORE_BACKEND=d1
CONVERSATIONS_D1_DATABASE_ID=<uuid>
```

Provision and migrate:

```bash
bun run cf:setup-conversations
bun run cf:migrate-conversations
```

The setup script creates the D1 database, stores the UUID in `wrangler.toml`, and adds the `CONVERSATIONS_D1` binding. The migration script applies the schema. During CI deploys, set `CONVERSATIONS_D1_DATABASE_ID` as a secret so `wrangler deploy` includes the binding. Without it, the binding is excluded from the deploy.

Also accepts `AGENT_CONVERSATIONS_D1_DATABASE_ID` as an alias for `CONVERSATIONS_D1_DATABASE_ID`.

**When to use:** standard Cloudflare deployments that want queryable, exportable conversation history.

## Postgres

Any PostgreSQL-compatible database.

```bash
CONVERSATION_STORE_BACKEND=postgres
DATABASE_URL=postgresql://user:password@host:5432/db
```

Also accepts `POSTGRES_URL` or `POSTGRES_PRISMA_URL` instead of `DATABASE_URL`. The runtime creates the `conversations` table and indexes if they do not exist. The database user needs `CREATE TABLE`, `CREATE INDEX`, `SELECT`, `INSERT`, `UPDATE`, and `DELETE` on the target schema.

**When to use:** Kubernetes, Docker, or any deployment with an existing Postgres instance.

## Memory

Ephemeral in-process store. Lost on process restart.

```bash
CONVERSATION_STORE_BACKEND=memory
```

Use only in development or tests.

## Browser (default)

Default when `VITE_FEATURE_CONVERSATION_DB` is not `true` or when the user is unauthenticated. No server config needed. History is stored in browser localStorage. Clearing browser data loses history.

## Deprecated alias

`NEXT_PUBLIC_FEATURE_CONVERSATION_DB=true` is equivalent to `VITE_FEATURE_CONVERSATION_DB=true` but is deprecated. Do not use it for new deployments.
