Laravel maintenance mode and health checks
Carlos Mendez
Jan 2026
3 tabs
{{-- resources/views/errors/503.blade.php --}}
<!DOCTYPE html>
<html>
<head>
<title>Maintenance Mode</title>
<style>
body {
font-family: sans-serif;
text-align: center;
padding: 50px;
}
</style>
</head>
<body>
<h1>We'll be right back!</h1>
<p>
@if(isset($exception) && $exception->getMessage())
{{ $exception->getMessage() }}
@else
Our site is currently undergoing scheduled maintenance.
@endif
</p>
<p>Please check back soon.</p>
</body>
</html>
# Enable maintenance mode
php artisan down
# With custom message
php artisan down --message="Upgrading Database"
# With retry header (seconds)
php artisan down --retry=60
# With secret bypass token
php artisan down --secret="my-secret-token"
# Access: https://example.com/my-secret-token
# Render custom view
php artisan down --render="errors.503"
# Disable maintenance mode
php artisan up
# Check if in maintenance mode
php artisan down --status
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
class HealthCheckController extends Controller
{
public function index()
{
$checks = [
'database' => $this->checkDatabase(),
'cache' => $this->checkCache(),
'queue' => $this->checkQueue(),
'storage' => $this->checkStorage(),
];
$healthy = collect($checks)->every(fn ($check) => $check['status'] === 'ok');
return response()->json([
'status' => $healthy ? 'healthy' : 'unhealthy',
'timestamp' => now()->toIso8601String(),
'checks' => $checks,
], $healthy ? 200 : 503);
}
private function checkDatabase(): array
{
try {
DB::connection()->getPdo();
return ['status' => 'ok'];
} catch (\Exception $e) {
return ['status' => 'error', 'message' => $e->getMessage()];
}
}
private function checkCache(): array
{
try {
Cache::put('health_check', true, 10);
$value = Cache::get('health_check');
return $value ? ['status' => 'ok'] : ['status' => 'error'];
} catch (\Exception $e) {
return ['status' => 'error', 'message' => $e->getMessage()];
}
}
private function checkQueue(): array
{
// Check last job processed time
$lastJob = DB::table('jobs')->latest('created_at')->first();
if (!$lastJob || $lastJob->created_at < now()->subMinutes(5)) {
return ['status' => 'warning', 'message' => 'No recent jobs'];
}
return ['status' => 'ok'];
}
private function checkStorage(): array
{
try {
Storage::put('health_check.txt', 'test');
Storage::delete('health_check.txt');
return ['status' => 'ok'];
} catch (\Exception $e) {
return ['status' => 'error', 'message' => $e->getMessage()];
}
}
}
3 files · blade, bash, php
Explain with highlit
Maintenance mode gracefully takes applications offline for updates without showing errors. The php artisan down command activates maintenance mode, showing a default or custom view. The --secret option creates bypass tokens for testing. The --retry header tells clients when to retry. Health check endpoints monitor application status for load balancers. I implement checks for database, cache, queue workers, and external dependencies. The up command restores normal operation. Maintenance mode uses a file lock preventing race conditions. For zero-downtime deployments, I use rolling restarts with health checks. This ensures reliable updates without user-facing errors.