Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pnpm build

Set `DATABASE_URL` (pooled), `DATABASE_URL_UNPOOLED` (direct), `PAYLOAD_SECRET`, `CRON_SECRET`, `PREVIEW_SECRET`, `NEXT_PUBLIC_SERVER_URL` and `BLOB_READ_WRITE_TOKEN`. The Blob token is injected automatically when a Vercel Blob store is connected to the project.

The initial migration is committed in `src/migrations`. Apply pending migrations using the direct connection before deploying:
Migrations are committed in `src/migrations`. On Vercel they are applied automatically: the `vercel-build` script runs `pnpm run db:migrate` (direct connection) before `next build`, on the Neon branch of each environment. See `docs/deployment.md`. Outside Vercel, run the same steps:

```bash
pnpm db:migrate
Expand Down
8 changes: 8 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ Never use the production connection for local development or preview deployments

`DATABASE_URL` uses the pooled hostname, while `DATABASE_URL_UNPOOLED` uses the direct hostname. The `db:migrate*` commands set `PAYLOAD_MIGRATING=true` so Payload selects the direct connection. Schema push is disabled; all changes use committed Payload migrations.

## Automatic migrations on deploy

Vercel runs the `vercel-build` script instead of `build` when it exists: `pnpm run db:migrate && pnpm run build`. Every deployment therefore applies pending Payload migrations to the Neon branch of its own environment (Preview → development branch, Production → production branch) over `DATABASE_URL_UNPOOLED`, before `next build`. Already-applied migrations are skipped, so a deploy without schema changes is a no-op for the database. If a migration fails, the build fails and the previous deployment keeps serving traffic.

Requirements: `DATABASE_URL_UNPOOLED`, `DATABASE_URL` and `PAYLOAD_SECRET` must be available to the build in each Vercel environment, and the project's *Build Command* setting must be left on its default (an override bypasses `vercel-build`).

Migrations must stay backward compatible with the deployment still serving traffic (additive changes first, removals in a later release), because the database is migrated before the new code goes live.

## Initial migration verification — 2026-09-09

Payload generated `20260909_073929` from the editorial collections, followed by two integrity migrations for authorship, research-source uniqueness, and query indexes. Development and production each contain 92 tables and all three `payload_migrations` records.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"db:migrate:status": "cross-env PAYLOAD_MIGRATING=true payload migrate:status",
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
"postbuild": "next-sitemap --config next-sitemap.config.cjs",
"vercel-build": "pnpm run db:migrate && pnpm run build",
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
"dev:prod": "cross-env NODE_OPTIONS=--no-deprecation rm -rf .next && pnpm build && pnpm start",
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
Expand Down
Loading