Running Laravel Migrations in Production Without Downtime
Production database migrations need care — locked tables, long ALTERs, and mismatched code can cause outages. Here's a practical playbook for safe Laravel migrations.
Migrations in development are forgiving — drop the database, re-run, move on. In production, a single ALTER TABLE on a 10 million row table can take down your site for minutes. Over the years I have built a small playbook for safe migrations. Here it is.
Avoid the dangerous operations on big tables
Adding a NOT NULL column with a default value, renaming a column, and adding indexes can all lock a MySQL table for the full migration. On small tables, this is fine. On large ones, it is an outage.
- Add new columns as NULLABLE first, then backfill in a separate job, then make NOT NULL.
- Use online schema change tools (pt-online-schema-change, gh-ost) for big tables.
- Postgres handles many of these better than MySQL — verify your engine's behavior.
Deploy code and migrations in the right order
If your code expects a new column that does not exist yet, requests will fail during the deploy window. The fix is to release in two phases: first ship code that tolerates the old schema, then run the migration, then ship code that uses the new schema.
It is more deploys, but each one is reversible. A single deploy that combines both is fast in the happy path and painful when anything goes wrong.
Always test the rollback
Every migration must have a working down() method, and you should test it locally before shipping. Laravel's migrate:rollback only works if down() actually reverses what up() did. A migration with empty down() is a one-way door — fine if you mean it, dangerous if you don't.
Run migrations before, not during, the deploy
If you run php artisan migrate as part of the deploy script and it fails halfway through, you are now in a half-migrated state with new code already on some servers. Run migrations as a separate, observed step. Most deploy tools support this — Forge, Envoyer, GitHub Actions all let you split the migrate step from the code release.
The shared theme: small, reversible, observable changes. Production migrations are not the place for cleverness. They are the place for boring, safe, verified procedure.
About the author

Richard Gamora
Fullstack developer based in the Philippines, working mostly with Laravel and Vue.js, with eight years of production experience across web and mobile.
More on Laravel
April 22, 2026
Why Laravel Queue Workers Stop — Common Causes and Fixes
Laravel queue workers can quietly stop processing jobs in production. Here's how to spot the common causes — memory limits, restarts, lost DB connections — and fix them.
April 15, 2026
Laravel N+1 Query Problem: How to Spot and Solve It
The N+1 query problem is the most common performance issue in Laravel apps. Here's how to detect it with the query log, fix it with eager loading, and prevent it from coming back.
April 8, 2026
Laravel API Resources vs Fractal — Which Should You Use
Laravel API Resources and Fractal both transform models into JSON. Here's how they compare on flexibility, includes, performance, and team ergonomics.