Skip to main content
Version: v2.0.0

Migrations

This page covers migration behavior for both database schema and storage data in OpenReader.

Startup migration behavior

By default, the shared entrypoint runs migrations automatically before app startup in:

  • Docker container startup
  • pnpm dev
  • pnpm start

Startup migration phases:

  • DB schema migrations (pnpm migrate)
  • Storage/data migration (pnpm migrate-fs) for legacy filesystem content into S3 + DB rows
info

In most setups, you do not need to run migration commands manually because startup handles this automatically.

To skip automatic startup migrations:

  • Set RUN_DRIZZLE_MIGRATIONS=false
  • Set RUN_FS_MIGRATIONS=false
warning

If you disable startup migrations, ensure your deployment process runs migrations before serving traffic.

Apply migrations

In most cases, you do not need manual migration commands because startup runs migrations automatically.

pnpm migrate applies migrations for one database target:

  • Postgres when POSTGRES_URL is set
  • SQLite when POSTGRES_URL is unset

You can always override the target explicitly with --config.

# Run pending migrations for one target:
# - Postgres if POSTGRES_URL is set
# - SQLite if POSTGRES_URL is unset
pnpm migrate

# Run storage migration (filesystem -> S3 + DB)
pnpm migrate-fs

# Dry-run storage migration without uploading/deleting
pnpm migrate-fs:dry-run

Generate migrations

pnpm generate is a two-phase script for contributors and schema changes:

  1. Better Auth schema generation — runs the Better Auth CLI twice (once for SQLite, once for Postgres) to produce auto-generated Drizzle schema files for auth tables (user, session, account, verification).
  2. Drizzle migration generation — runs drizzle-kit generate for both drizzle.config.sqlite.ts and drizzle.config.pg.ts, producing SQL migration files from all schema files (app + auth).
note

Most users do not need to run pnpm generate. Use it when contributing or when you have changed Drizzle schema files and need new migration files.

Schema ownership

Auth tables are owned by Better Auth. Their Drizzle schema definitions are auto-generated and should not be hand-edited:

  • src/db/schema_auth_sqlite.ts
  • src/db/schema_auth_postgres.ts

App-specific tables are manually maintained in the standard Drizzle schema files:

  • src/db/schema_sqlite.ts
  • src/db/schema_postgres.ts

Both sets of schema files are included in the Drizzle configs, so drizzle-kit generate and drizzle-kit migrate handle all tables together.

# Full pipeline: Better Auth CLI + Drizzle generate (both dialects)
pnpm generate