Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Health Check Bundle Laravel Package

kiora/health-check-bundle

A health check bundle for Symfony/PHP applications that exposes a monitoring endpoint and runs configurable checks to report service status, helping integrate with load balancers, uptime monitors, and container probes.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Confirm the framework fit first — this has not changed in v1.1.0. kiora/health-check-bundle is still a Symfony bundle, not a Laravel package, and the release notes are pure Symfony-bundle business (compiler passes, Kubernetes probes, bundle config tree). It will not composer require cleanly into a Laravel app as a drop-in service provider. Your first step is still a decision: (a) adopt it in a Symfony service that sits next to your Laravel app, or (b) use it as a reference implementation and port the handful of classes into a Laravel health controller.
  • Install and register (Symfony path). composer require kiora/health-check-bundle, then add the bundle to config/bundles.php. Pin the version explicitly ("kiora/health-check-bundle": "1.1.*" or the exact tag) — 1.1.0 added config keys and two new routes in a minor release, which is exactly the kind of churn that argues against a floating constraint on a package with a single active contributor.
  • Where to look first, in order: the AbstractHealthCheck base class and its new factory methods (that's the contract your custom checks extend), then the bundled controllers for /ping, /ready and the original endpoint, then the configuration tree (Configuration.php / DependencyInjection/) — the config surface grew meaningfully in 1.1.0 (groups, multiple database connections), so read it rather than assuming 1.0.0's shape. The source is still small enough to read end-to-end in ten minutes.
  • First use case, now with less work: wire /ping to your liveness probe and /ready to your readiness probe. v1.1.0 ships both, which removes the single biggest piece of hand-rolled wiring from the 1.0.0 assessment. Point them at a load balancer target group, an uptime monitor, or a Kubernetes probe and you have 90% of the value with almost no custom code.

Implementation Patterns

  • Custom checks as small classes. Extend AbstractHealthCheck (or implement the check interface), register it as a service, and let the bundle collect it via tag or autoconfigure. The new factory methods on AbstractHealthCheck cut the boilerplate for the common result shapes — healthy/unhealthy/skipped — so use them rather than constructing result objects by hand. Keep each check to one dependency — a PdoConnectionCheck, a RedisPingCheck, a DiskSpaceCheck — so a failure message tells you exactly what broke.
  • Use the group support for liveness vs readiness instead of building it. This was the top recommendation in the 1.0.0 assessment and 1.1.0 made it native: assign cheap, dependency-free checks to a liveness group and dependency-touching checks to a readiness group, and let /ping and /ready serve the respective groups. This is the single most valuable change in the release — liveness checks that hit the database are the classic cause of cascading restarts, and now you don't have to hand-roll the separation.
  • Multiple database connections are supported — but check one per group, not one per connection. The new multi-connection support makes it tempting to register a check for every connection in the config tree. Resist: a six-connection app produces six near-identical rows in the readiness payload and six round-trips per probe. Check the connections that actually matter for serving traffic (primary, and any connection on the hot path) and let the rest fail loudly in the app rather than in the probe.
  • Aggregate status, don't short-circuit. Let every check run and collect results, then compute the worst status. Short-circuiting on the first failure hides the fact that three things are down, which is exactly the information you want at 3am.
  • Use the new performance statistics in your response shape. v1.1.0 adds per-check timing, which is what you want in the payload anyway: status, checks[] with name, status, message, duration_ms. Stable field names so dashboards and alerting rules don't churn when you add a check. Never rename the top-level status field.
  • Laravel-side port, if you go that route — the blueprint just got better. The bundle's design now maps even more directly: a HealthController with /health/live and /health/ready actions mirroring /ping and /ready, a HealthCheck contract in app/Support/Health, checks registered via a tagged binding or a simple config array with group membership, and a HealthService that runs them and returns response()->json([...], $ok ? 200 : 503). Copy the group semantics and the response shape; skip the bundle wiring.
  • Gate deployments on it. Point your CI/CD smoke test at /ready after deploy and fail the release if it doesn't go green within N seconds. Still the highest-leverage use of a health endpoint and still about fifteen lines of pipeline YAML.
  • Wrap external checks in a timeout. Any check that makes a network call should have a hard timeout shorter than your probe's timeout, or a hung dependency makes the health endpoint itself hang and the probe reports a timeout instead of a useful failure. The new persistent-connection Redis check reduces per-probe cost but does not remove the need for a timeout.

Gotchas and Tips

  • The framework mismatch is still the big one. Everything in v1.1.0 is Symfony-shaped. Don't budget for "install and configure"; budget for "evaluate and possibly port." If your team is Laravel-only, the practical value here remains the design pattern — and 1.1.0 has made that pattern better (probe separation, groups, timing).
  • Upgrading from 1.0.0 is a config review, not a drop-in. The release adds group configuration, multi-connection database checks, and new routes. Re-read the config tree after bumping, confirm your existing check registrations still resolve to the groups you expect, and verify /ping and /ready are actually reachable (or deliberately disabled) behind your route/firewall setup. Read the changelog diff, not just the release title.
  • The in-memory cache is per-request, not a TTL cache. PR #17 prevents the same check running twice within one request — a real fix for duplicated execution, but it does not address probe fleet load. If your probe interval is 5s and a check takes 800ms, you're still burning capacity; a separate 10–30s result cache across requests is still on you.
  • Adoption risk is somewhat reduced but not resolved. New community files (CONTRIBUTING, SECURITY, CODE_OF_CONDUCT), CI workflows, and PHPStan level 9 are genuine maturity signals and worth credit. But v1.1.0 is still effectively one contributor's output — @james2001 authored every PR in the release — and the package is still a low-star, zero-dependent dependency. Pin the exact version, commit the lockfile, and keep the fork option open; the codebase is small enough that vendoring remains genuinely viable.
  • Check your autoconfiguration after upgrading. If a custom check silently doesn't run, the cause is almost always a missing tag or a service defined outside the scanned namespace — and with groups added, also a check that's tagged but not assigned to any group served by /ping or /ready. debug:container --tag=<check_tag> is the fastest way to confirm, then check the group mapping.
  • Don't leak internals. A health endpoint returning DSN fragments, stack traces, or internal hostnames is a free reconnaissance endpoint. The new multi-connection support makes this sharper — connection names in the payload can reveal your database topology. Restrict /ready at the network layer (internal-only listener, security firewall) or return generic messages publicly and log the detail.
  • Debugging a red status: hit the endpoint directly with curl -i to see the HTTP code before the body — a 200 with a failed-looking body usually means the aggregator isn't mapping check status to the response code, which is a config or version issue, not a check issue. With two new endpoints in the mix, first confirm which one your probe is actually hitting; a liveness probe pointed at /ready reintroduces the cascading-restart problem the release was meant to solve.
  • Extension points worth knowing: AbstractHealthCheck and its factory methods (the main one), group assignment config, the status-mapping/aggregation logic, and the route definitions for /ping and /ready if the bundle lets you override paths. If the routes aren't overridable, that's your signal to port rather than adopt.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource