Data

How to run database migrations on Replit production safely

Short answer

  • Replit keeps development and production databases separate. Schema changes made in dev must be applied to production.
  • Run a reviewed migration (for example drizzle-kit migrate) as part of each deploy, and read the SQL before it touches live data.
  • Renames often show up as drop plus add, which deletes data. Back up first: production has point-in-time restore.

Agent added a column, the preview works, and the published app now throws column "plan" does not exist. Or publishing shows a list of schema changes with scary DROP statements. Database migrations are where AI-built apps lose real data. Here is a safe routine that takes a few minutes per deploy.

Symptoms

  • column … does not exist or relation … does not exist only in production.
  • Publishing fails with a migration error, or shows schema changes to approve.
  • A tool warns that a change will cause data loss.
  • After a deploy, a column's values are empty.

Likely causes

  1. The schema changed in development and was never applied to production.
  2. Changes were pushed with a tool that diffs schemas directly, which can turn a rename into a drop and an add.
  3. Development and production schemas drifted after manual edits.
  4. An extension or type exists in one database and not the other.

Step-by-step fix

1. Back up before anything

Replit's production databases support point-in-time restore: up to 7 days of history on Core and up to 28 days on Pro, according to Replit's docs. Note the current time before you migrate so you know which moment to restore if something goes wrong. For extra safety, export the key tables.

2. Generate migration files, then read them

Prefer versioned migration files over pushing the schema directly. With Drizzle: drizzle-kit generate creates a SQL file you can read and commit.

npx drizzle-kit generate   # writes SQL into ./drizzle (or your migrations folder)
# open the new .sql file and look for DROP COLUMN, DROP TABLE, or a type change

3. Rewrite destructive changes

A rename should be ALTER TABLE … RENAME COLUMN, not drop plus add. A new required column needs a default or a backfill before NOT NULL. Deleting a column is a separate, later deploy once no code reads it.

4. Run migrations on every deploy

Replit's help center suggests adding the migration command to your deployment's build or pre-deploy step, so production is migrated each time you publish, for example npm run build && npx drizzle-kit migrate. If publishing shows schema changes to apply, read them as carefully as your own files.

5. Seed what production needs

Reference data (plans, roles, settings) must exist in production too. Use an idempotent seed script that inserts only missing rows.

Copy-paste prompt for Replit Agent

Open a new Agent chat (a fresh chat keeps old attempts out of its context) and paste this:

I need to apply my latest schema changes to the production database of my Replit app without losing data.
1. Generate versioned migration files (e.g. drizzle-kit generate) instead of pushing the schema directly.
2. Show me the SQL. Flag every DROP TABLE, DROP COLUMN, type change or NOT NULL without default.
3. Rewrite renames as RENAME COLUMN and add defaults/backfills for new required columns.
4. Add the migrate command to the deployment build step so it runs on each publish.
5. Write an idempotent seed script for reference data that only inserts missing rows.
Do not run anything against production until I confirm the SQL.

How to verify the fix

  • The Production view of the Database pane shows the new columns, with existing rows intact.
  • Row counts of key tables are the same before and after the deploy.
  • The pages that failed now work on the live URL.
  • The migrations table in production lists the new migration.

Rollbacks in the workspace do not restore production data. Read how Replit rollbacks treat your database before you rely on them.

FAQ

Does Replit migrate my production database automatically?

Development and production are separate databases. Replit may show schema changes to apply when you publish, and its help center recommends running your migration command in the build or pre-deploy step so it happens on each deploy.

Why did my migration delete a column's data?

Schema-diff tools often cannot tell a rename from a drop plus a new column. Read generated SQL and write renames explicitly.

How do I undo a bad migration in production?

Use point-in-time restore on the production database to a moment before the migration. Replit's docs list up to 7 days of history on Core and up to 28 days on Pro.

Get a free audit