Skip to content
Feeblo Docs
Esc
navigateopen⌘Jpreview
On this page

Database

Postgres for Feeblo. The DATABASE_URL shape, compose defaults, and the migration lifecycle from schema change to deployed schema.

Feeblo keeps all of its state in one PostgreSQL database. The compose stack runs PostgreSQL 17 with the pgvector extension, and the server container applies migrations itself on every start, so a production database mostly runs itself. The db: scripts matter when you develop locally, manage the schema by hand, or recover a broken instance.

Connection string

The database URL follows the standard Postgres shape:

DATABASE_URL="postgres://feeblo:password@127.0.0.1:54323/feeblo"
Part Meaning
feeblo user, POSTGRES_USER in compose
password password, POSTGRES_PASSWORD in compose
127.0.0.1 host the server can reach
feeblo database name, POSTGRES_DB in compose

Compose fills in sensible defaults for you:

  • The pg container reads POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB from .env, each defaulting to feeblo, password, feeblo.
  • The server gets DATABASE_URL defaulting to postgres://feeblo:password@pg:5432/feeblo. The host is pg because that is the service name inside the compose network.
  • On the host, Postgres publishes to ${POSTGRES_PORT:-5432}:5432, so a local client connects to 127.0.0.1:5432 by default. The dev stack uses port 54323 instead.

Migration lifecycle

Schema lives in packages/db/src/schema/ (four files: auth.ts, feedback.ts, integration.ts, media.ts). Drizzle generates versioned SQL migrations from them into packages/db/src/migrations/.

Change the schema

Edit the Drizzle schema in packages/db/src/schema/. Add tables, columns, or indexes the same way you would in any Drizzle project.

Generate the migration

pnpm db:generate

drizzle-kit generate diffs the schema against the last migration and writes a new timestamped folder under packages/db/src/migrations/. Review the SQL it produced.

Commit the migration

Migrations are code. Commit the generated folder with the schema change so the next deploy carries it.

Apply it locally or deploy it

pnpm db:migrate

drizzle-kit migrate applies every pending migration to the DATABASE_URL found in the root .env file and records it in the __drizzle_migrations table.

Production never runs this command. The server image runs its own migration runner (node ./migrate/index.js) before it starts listening, so a deploy applies pending migrations automatically. See Deploy with Docker for the upgrade flow.

The db: scripts

All scripts run from the repo root and load .env through dotenvx, so keep DATABASE_URL in your root .env before running any of them.

Script What it does
pnpm db:start Start the local database container (docker compose up -d)
pnpm db:watch Same, with logs attached (docker compose up)
pnpm db:generate Generate SQL migrations from schema changes
pnpm db:migrate Apply pending migrations
pnpm db:push Push the schema without a migration file (drizzle-kit push)
pnpm db:seed Fill the database with sample data
pnpm db:studio Open Drizzle Studio against the database
pnpm db:nuke Erase every row in every table
pnpm db:stop Stop the database container
pnpm db:down Stop and remove the container (data volume survives)

pnpm db:push is the fast path for throwaway development databases: it applies the schema directly instead of going through migrations. On a shared or production database, prefer generated migrations, because push leaves no migration record for other environments to replay.

Local development stack

The dev compose file at docker/docker-compose.dev.yml defines Postgres, Redis, MinIO, and Mailpit:

docker compose -f docker/docker-compose.dev.yml up -d

Postgres publishes on port 54323, which is exactly what the DATABASE_URL default in .env.example points at (postgres://feeblo:password@127.0.0.1:54323/feeblo). A fresh local checkout needs three commands:

pnpm db:migrate
pnpm db:seed
pnpm dev

pnpm db:seed creates an admin user and sample data so the dashboard has something to show. Re-run db:migrate whenever you pull changes that contain new migrations.

If you change embedding dimensions, run pnpm db:configure-embeddings to resize the vector column; the Docker page explains when that is needed.

Next steps

Was this page helpful?