ans-group/laravel-health-check
A Laravel package for monitoring application health. It provides configurable checks for services such as database, cache, queue, and storage, with routes and commands to verify readiness and liveness in production.
ans-group/laravel-health-check gives you a ready-made /health endpoint (route and path are configurable) plus a set of built-in dependency checks, so you can wire your app into a load balancer, Kubernetes probe, or uptime monitor in minutes.
v3.0.0 platform requirements — check these before anything else:
Minimal steps:
composer require ans-group/laravel-health-check:^3.0php artisan vendor:publish — confirm the exact tag in the README, it varies by version) and skim config/health-check.php; this is the file you'll actually live in./health in the browser or curl -i http://localhost:8000/health. You should get a JSON payload with an overall status and per-check results; unhealthy checks should drive a non-2xx response.If you're on Laravel 10/11 or PHP 8.1, stay on ^2.1 — v3 will simply not install.
Split liveness from readiness. Probes firing every 5–10 seconds should not hammer your database. Either configure a cheap route for liveness (app booted, no I/O) and a fuller one for readiness, or disable expensive checks and rely on the cheap ones for the frequent probe.
Custom checks. Write one class per dependency, keep it to a single bounded call, and fail fast with a short timeout. Good candidates beyond the defaults: S3/SES reachability, a third-party API you hard-depend on, a migrations-pending check, disk-free-space, or a "critical config value is non-empty" assertion. Avoid anything with side effects — no writes, no queue dispatch, no cache warmups — since this runs continuously in production.
Per-environment config. Keep the full check set in staging/production and trim aggressively in local (a failing Redis container shouldn't make php artisan serve look broken). Drive this from env vars in the config file rather than editing config per machine.
Cache the result briefly. If your probe interval is short, memoize the aggregate result for 5–15s (cache store, not memory) so a 3-replica deployment with a 5s probe isn't running 36 DB round-trips a minute.
Deploy gating. After a rolling deploy or migration, curl -fsS https://app/health in CI/CD and fail the pipeline on non-2xx. This catches "deployed but .env key missing" far earlier than a user report.
Monitoring integration. The JSON body is easier to consume than the status code alone — ship it to Datadog/Prometheus/CloudWatch as a gauge per check name, and alert on the aggregate. Emitting check durations is worth the extra parsing when you're debugging a slow dependency.
Testing. A feature test asserting 200 + the JSON shape on a healthy app, and a test that stubs a failing dependency (e.g. Http::fake() a 500 for an HTTP check) to assert the degraded path. This is where teams usually discover their endpoint accidentally returns 200 on failures.
Access control. The endpoint is public by default. Either restrict it by IP/middleware at the edge, or accept leakage of dependency names and versions deliberately — but decide explicitly, don't inherit the default.
v3.0.0 is a breaking release on two axes. Laravel ≥12 and PHP ≥8.2 only. Upgrade sequence:
composer why-not laravel/framework 12.*).composer require ans-group/laravel-health-check:^3.0 --with-all-dependencies.php artisan config:cache && php artisan route:cache locally to catch cached-config surprises before prod does.${} interpolation) surface in subclasses, not in the package itself.Liveness probes must not include dependency checks. A DB blip that fails a liveness check gets your pods killed and restarted in a loop, which turns a 30-second outage into a 10-minute one. DB/Redis/HTTP checks belong only on readiness.
config:cache in production freezes the check list and any env-driven toggles. Changing HEALTH_CHECK_* in .env without php artisan config:cache will appear to do nothing — a classic half-hour debug.
Queue checks mislead on the sync driver (and on null). Configure the queue check per environment or disable it offline; otherwise local/staging reports a false failure.
Storage checks write a temp file. On read-only filesystems (containers with a RO root) or a nearly-full disk this fails for the wrong reason. Point it at a writable, non-critical disk and clean up after itself.
Database checks against read replicas / read-only connections can fail depending on what the check does. Verify against your actual connection config, not just your local primary.
Slow checks = flapping. A check that occasionally takes 10s will flap under timeoutSeconds: 1. Measure each check's p95 before enabling it, and set probe timeouts above that.
Don't leak detail publicly. Full per-check output with driver names, hostnames, and exception messages is reconnaissance for an attacker. Gate verbose output behind an auth middleware or APP_DEBUG, and keep the public response to a bare status.
Extension points worth knowing: custom check classes registered in the config's check list, per-check enable/disable toggles, the route path/prefix and middleware in config, and the aggregate response shape. Those four cover almost every real-world need — reach for them before forking the package.
How can I help you explore Laravel packages today?