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
- Docker Desktop (or Docker Engine)
- The normal local dev setup from
LOCAL_DEVELOPMENT.md
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.