Copied to clipboard

PostgreSQL Storage

tapes stores every session in PostgreSQL. The same database holds the Merkle DAG, session aggregates, and vector embeddings.

Requirements

The database must have two extensions installed:

  • pg_duckdb — powers the recursive columnar queries behind /v1/stems/:hash and /v1/stats.
  • pgvector — stores embeddings for semantic search.

Schema migrations run automatically on tapes serve startup. There is no separate tapes migrate step.

Quick Start

The fastest path is tapes local up, which starts a Postgres image with pg_duckdb + pgvector preinstalled and an Ollama container alongside it:

tapes local up
tapes serve --postgres "postgres://tapes:tapes@localhost:5432/tapes?sslmode=disable"

Already running your own Postgres? Skip tapes local up and supply your DSN directly — provided the two extensions are installed.

Run Postgres yourself

If you'd rather manage the container yourself, use the same image tapes local up uses (it bundles both extensions):

1. Start PostgreSQL

docker run -d --name tapes-postgres \
  -e POSTGRES_USER=tapes \
  -e POSTGRES_PASSWORD=tapes \
  -e POSTGRES_DB=tapes \
  -p 5432:5432 \
  public.ecr.aws/g4e5l3z3/papercomputeco/postgres:17.7-pgduckdb-1.1.1

2. Start tapes

tapes serve --postgres "postgres://tapes:tapes@localhost:5432/tapes?sslmode=disable"

3. Verify

curl http://localhost:8081/ping

Remote PostgreSQL

Use a hosted PostgreSQL provider for team-wide shared storage. Any PostgreSQL-compatible service works:

  • Supabase — Managed Postgres with built-in auth and dashboard
  • Neon — Serverless Postgres with branching and autoscaling
  • PlanetScale — High-availability Postgres on NVMe storage with database branching
  • AWS RDS — Self-managed Postgres on AWS infrastructure

Example: Supabase

  1. Create a project at supabase.com
  2. Go to Project Settings > Database and copy the connection string
  3. Start tapes with the remote DSN:
tapes serve \
  --postgres "postgres://postgres.[project-ref]:[password]@aws-0-us-east-1.pooler.supabase.com:6543/postgres" \
  --provider anthropic \
  --upstream "https://api.anthropic.com"

Each team member runs their own proxy instance pointing to the same remote database. All conversations are visible to everyone.

Deployed frontends need a reachable proxy

If your frontend runs on a hosted platform (Vercel, Netlify, etc.), the tapes proxy must also be running somewhere accessible over the network — localhost won't work. You can deploy the proxy to any cloud provider that runs containers. A hosted tapes Cloud service is in development that will remove this requirement.

Config File

Save the connection string in .tapes/config.toml so you don't need the flag every time:

# .tapes/config.toml
[storage]
postgres_dsn = "postgres://user:pass@host:5432/tapes?sslmode=require"

CLI flags override config file values. Use tapes config set storage.postgres_dsn <dsn> to set it without editing the file directly.

Vercel AI SDK Integration

Route Vercel AI SDK requests through tapes to capture conversations in PostgreSQL. Point the provider's baseURL at your tapes proxy. For a complete working example, see tapes-ai-sdk-example (opens in new tab).

import { createAnthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';

const anthropic = createAnthropic({
  baseURL: 'http://localhost:8080',
});

const { text } = await generateText({
  model: anthropic('claude-sonnet-4-5'),
  prompt: 'Explain merkle trees in one paragraph.',
});

For OpenAI models:

import { createOpenAI } from '@ai-sdk/openai';

const openai = createOpenAI({
  baseURL: 'http://localhost:8080/v1',
});

Start tapes with the matching provider flag: --provider anthropic or --provider openai.

The example repo also supports TAPES_POSTGRES_DSN as an environment variable, so you can configure the storage backend without changing code:

# .env
TAPES_POSTGRES_DSN="postgres://user:pass@localhost:5432/tapes"

Team Setup

A typical team deployment:

  1. Provision a shared PostgreSQL database (Neon, Supabase, RDS)
  2. Add the DSN to each developer's ~/.tapes/config.toml
  3. Each developer runs tapes start claude or tapes serve locally
  4. All conversations flow into the shared database
  5. Use tapes deck or the API to query across the entire team's history

Next Steps

Last updated: