Framework Guide

Laravel Health Check

Set up health check endpoints and uptime monitoring for your Laravel application. Simple patterns for production-ready monitoring.

Simple Health Route

// routes/web.php or routes/api.php
Route::get('/health', function () {
    return response()->json([
        'status' => 'healthy',
        'timestamp' => now()->toISOString()
    ]);
});

Health Controller

// app/Http/Controllers/HealthController.php
namespace App\Http\Controllers;

use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;

class HealthController extends Controller
{
    public function health(): JsonResponse
    {
        return response()->json(['status' => 'healthy']);
    }

    public function ready(): JsonResponse
    {
        $checks = [];
        $healthy = true;

        // Check database
        try {
            $start = microtime(true);
            DB::select('SELECT 1');
            $checks['database'] = [
                'status' => 'ok',
                'response_time_ms' => round((microtime(true) - $start) * 1000, 2)
            ];
        } catch (\Exception $e) {
            $healthy = false;
            $checks['database'] = [
                'status' => 'error',
                'message' => $e->getMessage()
            ];
        }

        // Check cache/Redis
        try {
            $start = microtime(true);
            Cache::put('health_check', 'ok', 10);
            Cache::get('health_check');
            $checks['cache'] = [
                'status' => 'ok',
                'response_time_ms' => round((microtime(true) - $start) * 1000, 2)
            ];
        } catch (\Exception $e) {
            $healthy = false;
            $checks['cache'] = [
                'status' => 'error',
                'message' => $e->getMessage()
            ];
        }

        return response()->json([
            'status' => $healthy ? 'healthy' : 'unhealthy',
            'timestamp' => now()->toISOString(),
            'checks' => $checks,
            'version' => config('app.version', 'unknown')
        ], $healthy ? 200 : 503);
    }
}

// routes/web.php
Route::get('/health', [HealthController::class, 'health']);
Route::get('/ready', [HealthController::class, 'ready']);

Using spatie/laravel-health

For a more robust solution, use the Spatie health package:

# Install
composer require spatie/laravel-health
php artisan vendor:publish --tag="health-config"

# config/health.php
use Spatie\Health\Checks\Checks\DatabaseCheck;
use Spatie\Health\Checks\Checks\CacheCheck;
use Spatie\Health\Checks\Checks\RedisCheck;
use Spatie\Health\Checks\Checks\UsedDiskSpaceCheck;

return [
    'checks' => [
        DatabaseCheck::new(),
        CacheCheck::new(),
        RedisCheck::new(),
        UsedDiskSpaceCheck::new()
            ->warnWhenUsedSpaceIsAbovePercentage(70)
            ->failWhenUsedSpaceIsAbovePercentage(90),
    ],
];

# routes/web.php
use Spatie\Health\Http\Controllers\HealthCheckResultsController;

Route::get('/health', HealthCheckResultsController::class);

Exclude from CSRF

// app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
    'health',
    'ready',
];

Check Queue Health

// Check if queue workers are running
try {
    $queueSize = Queue::size('default');
    $checks['queue'] = [
        'status' => $queueSize < 1000 ? 'ok' : 'warning',
        'pending_jobs' => $queueSize
    ];
} catch (\Exception $e) {
    $checks['queue'] = [
        'status' => 'error',
        'message' => $e->getMessage()
    ];
}

Best Practices

  • Skip middleware — Health checks shouldn't require auth or CSRF
  • Check queue workers — Verify background jobs are processing
  • Monitor disk space — Laravel logs can fill up disks
  • Check scheduled tasks — Ensure cron is running

Monitor your Laravel API

Add your health endpoint to UptimeSignal and get alerted when it fails.

Start monitoring free →

More Framework Guides