Move your app from one server to other without downtime (for reading)
If your database is small (< 1 GB), you can simply:
- php artisan down
- mysqldump …
- php artisan up
For larger websites (5 GB+ databases), follow the steps below:
So, you want to move from one server to another? But it can take time, from few minutes to hours. Or if you are going to move to other hosting provider, you will need backup database and import which can take few hours.
So what to do if you don’t wanna users to stare at black screen and search agents to fail to get pages?
If you use laravel you can block non-GET requests and show a “read-only mode” error for few minutes/hours.
If you are making a snapshot image (same provider)
Turn off your server
Create a full server snapshot
Restore the snapshot on the new server or VM.
[OLD SERVER] Add read-only middleware:
Inapp/Http/Kernel.php
, add theBlockPostRequest
middleware to all groups (web
,api
, etc.).[OLD SERVER] Stop background workers (if any):
sudo supervisorctl stop laravel-worker:*
[OLD SERVER] Pause scheduled tasks:
Edit crontab (crontab -e
) and comment out Laravel’s scheduler:# * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
After the new server installed with snapshot, update DNS records to point to the new server.
Shutdown the old server once everything is verified.
If you are moving to another hosting provider (database dump)
Add read-only middleware:
Inapp/Http/Kernel.php
, add theBlockPostRequest
middleware to all groups (web
,api
, etc.).Stop background workers (if any):
sudo supervisorctl stop laravel-worker:*
Pause scheduled tasks:
Edit crontab (crontab -e
) and comment out Laravel’s scheduler:# * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Export the database:
mysqldump -u your_user -p your_database > backup.sql
Import the database on the new server.
Update DNS records to point your domain to the new server IP.
Shutdown the old server once everything is verified.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class BlockPostRequest
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->method() !== 'GET') {
abort(503, "Website is temporarily in read-only mode.");
}
return $next($request);
}
}
Notes:
- In the snapshot method, stopping workers and cron is recommended — for example, to avoid wasting limited external API credits or triggering unnecessary background jobs, since the old server will be shut down soon.
- If you use another framework, similar read-only techniques likely exist.
- Alternatively, you can temporarily configure a read-only database user with no
INSERT
,UPDATE
, orDELETE
permissions.
Now you can move servers without panic — users can still browse your website during the migration, and in most cases (97%), visitors don’t write anything anyway!