Skip to content

Health for Laravel: Kubernetes Probes and Prometheus Metrics

The cboxdk/laravel-health package adds dedicated Kubernetes liveness, readiness, and startup probe endpoints plus a Prometheus-scrapable /health/metrics route to any Laravel 11, 12, or 13 application.

Published · Updated · 4 min read

Health for Laravel: Kubernetes Probes and Prometheus Metrics

What Is Health for Laravel?

cboxdk/laravel-health is a package by Sylvester Damgaard that goes well beyond Laravel's built-in /up route. It registers three Kubernetes-ready probe endpoints, a Prometheus scrape target, and a CLI command — all configurable from a single config/health.php file.

Key Features at a Glance

  • Three Kubernetes probe endpoints: /health (liveness), /health/ready (readiness), /health/startup
  • 10 built-in checks: database, cache, queue, storage, Redis, environment, schedule, CPU, memory, and disk space
  • Prometheus metrics at /health/metrics with per-check status and duration gauges
  • Container-aware memory reporting via cgroup v1 and v2
  • JSON metrics at /health/metrics/json including the pod name
  • health:check Artisan command that exits non-zero on failure
  • Response caching (10-second default) and an optional HTML dashboard at /health/ui

Assigning Checks to Each Kubernetes Probe

Each probe type gets its own list of checks in config/health.php:

use Cbox\LaravelHealth\Checks\{
    CacheCheck, DatabaseCheck, EnvironmentCheck,
    QueueCheck, RedisCheck, StorageCheck
};

'checks' => [
    'liveness'  => [DatabaseCheck::class],
    'readiness' => [
        DatabaseCheck::class,
        CacheCheck::class,
        RedisCheck::class,
        QueueCheck::class,
        StorageCheck::class,
    ],
    'startup'   => [EnvironmentCheck::class],
],

A probe endpoint returns 200 when every check is ok or warning, and 503 when any check is critical or unknown. Your Kubernetes deployment manifest maps each path to the correct probe:

livenessProbe:
  httpGet:
    path: /health
    port: 80
  periodSeconds: 15

readinessProbe:
  httpGet:
    path: /health/ready
    port: 80
  periodSeconds: 10

startupProbe:
  httpGet:
    path: /health/startup
    port: 80
  failureThreshold: 30
  periodSeconds: 5

Prometheus Metrics

The /health/metrics endpoint exposes two gauges per check:

  • app_health_check_status — 1.0 (ok), 0.5 (warning), 0.0 (critical/unknown)
  • app_health_check_duration_seconds — how long the check took

The app prefix is controlled by the HEALTH_PROMETHEUS_NAMESPACE environment variable. System-level metrics (load averages, memory, disk per mount, network per interface, uptime) come from the companion cboxdk/system-metrics package. Inside a container, five additional metrics are added, including app_container_memory_limit_bytes, app_container_cpu_quota, and app_container_oom_kills_total.

Monitoring the Task Scheduler

ScheduleCheck reads a heartbeat timestamp written by the health:heartbeat Artisan command. Schedule it in routes/console.php:

Schedule::command('health:heartbeat')->everyMinute();

The check returns critical when the heartbeat is older than max_age_minutes (default: 5). Add it to the readiness list and Kubernetes will stop routing traffic to any pod whose scheduler has stalled.

Writing a Custom Check

Extend BaseCheck, implement run(), and return a CheckResult:

namespace App\Health;

use Cbox\LaravelHealth\Checks\BaseCheck;
use Cbox\LaravelHealth\DataTransferObjects\CheckResult;
use Illuminate\Support\Facades\Http;

class PaymentGatewayCheck extends BaseCheck
{
    public function run(): CheckResult
    {
        try {
            $response = Http::timeout(5)->get('https://payments.example.com/health');
        } catch (\Throwable $e) {
            return CheckResult::critical($this->name(), $e->getMessage());
        }

        return $response->successful()
            ? CheckResult::ok($this->name())
            : CheckResult::critical($this->name(), "HTTP {$response->status()}");
    }
}

CheckResult has four named constructors — ok(), warning(), critical(), and unknown() — each accepting an optional metadata array that appears in JSON responses.

Installation

Requires PHP 8.3 and Laravel 11, 12, or 13:

composer require cboxdk/laravel-health
php artisan vendor:publish --tag="health-config"

Verify the setup from the terminal:

php artisan health:check
php artisan health:check --endpoint=readiness

The HEALTH_PREFIX environment variable changes the /health base path if you prefer paths like /livez or /readyz.

Real Takeaways

  • Separate check lists per probe type give Kubernetes precise restart and traffic-routing signals.
  • The Prometheus endpoint requires no extra exporter — just point your scrape config at /health/metrics.
  • Container-aware cgroup metrics mean memory figures reflect actual container limits, not host totals.
  • ScheduleCheck + health:heartbeat provides a simple, cache-backed scheduler watchdog.
  • Custom checks are a single class with four possible result states and optional metadata.

Source: Health for Laravel: Kubernetes Probes and Prometheus Metrics — Laravel News

Frequently asked questions

What is the difference between the liveness and readiness probe endpoints in this package?

The liveness probe at `/health` tells Kubernetes whether to restart the container — a failure triggers a restart. The readiness probe at `/health/ready` tells Kubernetes whether to route traffic to the pod; a failure removes the pod from the load balancer without restarting it. You assign a different set of checks to each probe in `config/health.php`.

How does the ScheduleCheck know whether the Laravel task scheduler is running?

You schedule the `health:heartbeat` Artisan command to run every minute. It writes a timestamp to the cache. `ScheduleCheck` reads that timestamp and returns `critical` if it is older than `max_age_minutes` (default: 5), giving Kubernetes a signal to stop routing traffic to a pod with a stalled scheduler.

Does the Prometheus metrics endpoint require a separate exporter process?

No. The `/health/metrics` endpoint is served directly by your Laravel application. Prometheus scrapes it like any other HTTP target. System and container metrics are provided by the `cboxdk/system-metrics` companion package, so no sidecar or external exporter is needed.

Mohamed Said

About the author

Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

About GitHub LinkedIn WhatsApp Email Address My CV

Have a technical challenge?

Tell me what you’re building. I reply within two working days.

Discuss your project