metatron-open-seo/docs/LOCAL_POSTGRES.md

3.0 KiB

Running OpenSEO on Postgres locally

OpenSEO runs on Cloudflare D1 (SQLite) by default. Postgres is an opt-in backend for installs that outgrow D1's storage ceiling. The application code is written once against a provider-aware db layer (see src/db/), so the only difference at runtime is the DATABASE_PROVIDER flag and a connection string.

This guide sets up a throwaway Postgres in Docker so you can develop and test the Postgres path locally. You do not need this for normal development — D1 is the default and the path most contributors should use.

Prerequisites

1. Start a Postgres container

Port 5433 is used on the host to avoid clashing with a system Postgres on the default 5432.

docker run --name openseo-postgres \
  -e POSTGRES_USER=openseo \
  -e POSTGRES_PASSWORD=openseo \
  -e POSTGRES_DB=openseo \
  -p 5433:5432 \
  -d postgres:16

Wait until it accepts connections:

docker exec openseo-postgres pg_isready -U openseo -d openseo

The connection string is:

postgres://openseo:openseo@localhost:5433/openseo

2. Apply the Postgres migrations

The Postgres schema is hand-written (it is the one structural artifact db:generate does not regenerate) and migrations live in drizzle-pg/. Apply them with POSTGRES_DATABASE_URL set — drizzle-kit reads it from the shell environment:

POSTGRES_DATABASE_URL=postgres://openseo:openseo@localhost:5433/openseo \
  pnpm db:migrate:pg

3. Point the app at Postgres

The Cloudflare Vite runtime reads Worker vars from .env.local, so set both values there (not just in your shell):

# .env.local
DATABASE_PROVIDER=postgres
POSTGRES_DATABASE_URL=postgres://openseo:openseo@localhost:5433/openseo

Then start the dev server as usual:

pnpm dev

To switch back to D1, remove those two lines (or set DATABASE_PROVIDER=d1) and restart.

4. Verify

# Tables created by the migrations
docker exec openseo-postgres psql -U openseo -d openseo -c "\dt"

# Inspect rows the app writes (e.g. after creating a project / saving keywords)
docker exec openseo-postgres psql -U openseo -d openseo -c "select count(*) from projects;"

Schema changes

When you change a table, update both dialects:

  • SQLite: src/db/*.schema.ts (+ pnpm db:generate:d1)
  • Postgres: src/db/pg/*.schema.ts (+ pnpm db:generate:pg)

src/db/schema-parity.test.ts fails CI if the two dialects drift (mismatched tables, columns, nullability, primary keys, unique/partial indexes, or FK onDelete). It compares the schema definitions, not the generated migrations — so after editing the Postgres schema, always run pnpm db:generate:pg and commit the new drizzle-pg/ migration, or a Postgres deploy will be missing the change even though the parity test is green.

Teardown

docker rm -f openseo-postgres

This deletes the container and all its data. Re-run from step 1 for a clean slate.