Classic server apps often run pending migrations at boot. On serverless that instinct is a footgun: your “boot” happens on every cold start, concurrently, on whatever instance wakes up first. Migrations racing each other from lambda cold starts is not a place you want to be.
The pattern that works: run migrations in the build step. On Netlify, the build environment gets the production database URL injected (NETLIFY_DATABASE_URL with their Neon integration), so the build can apply pending Drizzle migrations plus idempotent seeds exactly once per deploy — before the new function version ever ships:
# netlify.toml
command = "cd backend && npm install && npm run db:migrate && npm run db:seed && cd ../web && npm run build"
The function itself never touches migration code. A deploy either migrates and ships together, or fails together — no half-migrated running version.