Your app is running perfectly at 3 AM, but by morning it's completely dead. Sound familiar? Health check endpoints are like having a nurse check on your app every few minutes.
Table Of Contents
The Basic Setup
// routes/api.php
Route::get('/health', [HealthController::class, 'check']);
// app/Http/Controllers/HealthController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
class HealthController extends Controller
{
public function check()
{
$status = 'healthy';
$checks = [];
// Database check
try {
DB::connection()->getPdo();
$checks['database'] = 'healthy';
} catch (\Exception $e) {
$checks['database'] = 'unhealthy';
$status = 'unhealthy';
}
// Cache check
try {
Cache::put('health_check', 'test', 5);
Cache::get('health_check');
$checks['cache'] = 'healthy';
} catch (\Exception $e) {
$checks['cache'] = 'unhealthy';
$status = 'unhealthy';
}
$response = [
'status' => $status,
'timestamp' => now()->toISOString(),
'checks' => $checks
];
return response()->json($response, $status === 'healthy' ? 200 : 503);
}
}
Advanced health check with multiple services:
public function check()
{
$checks = [
'database' => $this->checkDatabase(),
'redis' => $this->checkRedis(),
'storage' => $this->checkStorage(),
'external_api' => $this->checkExternalApi(),
];
$healthy = collect($checks)->every(fn($check) => $check['status'] === 'healthy');
return response()->json([
'status' => $healthy ? 'healthy' : 'unhealthy',
'timestamp' => now()->toISOString(),
'version' => config('app.version', '1.0.0'),
'environment' => app()->environment(),
'checks' => $checks
], $healthy ? 200 : 503);
}
private function checkDatabase(): array
{
try {
$start = microtime(true);
DB::select('SELECT 1');
$duration = round((microtime(true) - $start) * 1000, 2);
return ['status' => 'healthy', 'response_time' => "{$duration}ms"];
} catch (\Exception $e) {
return ['status' => 'unhealthy', 'error' => $e->getMessage()];
}
}
The Health Check Protocol
The rules are simple: return 200 when everything's fine, 503 when something's broken. Your load balancer reads these status codes like a doctor reading vitals - 200 means "keep sending traffic," 503 means "this server needs help."
Simple one-liner health check:
// For basic needs
Route::get('/ping', fn() => response()->json(['status' => 'pong', 'timestamp' => now()]));
// With app info
Route::get('/status', fn() => response()->json([
'app' => config('app.name'),
'version' => config('app.version'),
'environment' => app()->environment(),
'uptime' => now()->diffInSeconds(new \DateTime('@' . $_SERVER['REQUEST_TIME']))
]));
Related: Laravel Collections: Beyond Basic Array Operations | Laravel Events and Listeners: Building Decoupled Applications | Building Multi-tenant Applications with Laravel: A Comprehensive Guide | Laravel Health Checks: Monitor App State in 2025 | Performance Optimization: Speed in Web Applications
Add Comment
No comments yet. Be the first to comment!