Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

caterpillar123's avatar

Run Laravel migrations on just one server (like ->onOneServer() for scheduled jobs)

I'm running a Laravel app on multiple servers at the same time. It's running in a Docker image. Each time I deploy some code changes, Docker image is restarted and then it runs after_deployment.sh script which contains php artisan migrate --force. This script is executed by ALL of my servers, not just one.

All servers use the same central DB. So if two servers try to run the php artisan migrate at roughly the same time, only the first server succeeds, the other fails somewhere in the middle and logs an error. This is not great.

There was a similar problem with running cronjobs (Laravel Scheduler) on just one server, but that is now solved as Laravel provides the ->onOneServer(); method for Scheduled jobs.

Is there something similar for running migrations on just one server? Something like php artisan migrate --force --on-one-server?

0 likes
5 replies
Snapey's avatar

You could have a an env flag in the server you want to run the migrations ?

caterpillar123's avatar

@Snapey env flag would be a good option in many cases. However, this time I'm running my app on Azure App Service. It's a very simplified environment in comparison with something like Kubernetes. It allows me to easily scale beyond 1 server instance, but it only allows me to set ENV variables in one central location and then it applies those ENV variables to ALL the servers. In this hosting environment, I simply cannot set ENV flag for just one of the servers.

Snapey's avatar

it wouldn't matter if they did not run at the same time. any way you can stagger the deployment?

caterpillar123's avatar

@Snapey I guess 95% of the time there will be at least a few seconds difference between servers getting updated, but it's not guaranteed. I don't see any out-of-the-box way to stagger the deployment in Azure App Service.

I can either hope my servers don't attempt to run migrations at the same time, or invent some lock mechanism myself. Maybe set and check a certain key in Redis cache (which is shared across all server instances) before running the migrations. I guess that's roughly what ->onOneServer(); does for cronjobs.

Snapey's avatar

@caterpillar123 maybe check for the existence of the table in the migration file. if it exists then sleep for 10 seconds then continue?

if two start at roughly the same time then the second sees that the table exists and skips to the next migration. since the second is doing no work, it overtakes the first and you end up with this fight. by adding the delay you are forcing one server to stay behind the other

Please or to participate in this conversation.