xrow/healthcheck-bundle
A Symfony bundle that adds health check endpoints to your application so load balancers and uptime monitors can verify that services such as the database, cache, and filesystem are responding correctly.
Pull the bundle in via Composer and register it like any Symfony bundle:
composer require xrow/healthcheck-bundle
// config/bundles.php
return [
// ...
Xrow\HealthcheckBundle\XrowHealthcheckBundle::class => ['all' => true],
];
Import the bundle's routing with whatever prefix your infrastructure expects (path is arbitrary — pick one and stick to it across environments):
# config/routes.yaml
xrow_healthcheck:
resource: '@XrowHealthcheckBundle/Resources/config/routing.yaml'
prefix: /_health
Smoke test it before wiring anything into a load balancer:
curl -i https://your-app.test/_health
# expect 200 + JSON body; 503 if a dependency is down
Where to look first — read the bundle source in this order, because the README on a low-traffic vendor bundle is often behind the code:
Resources/config/routing.yaml — the real endpoint paths and HTTP methods.DependencyInjection/Configuration.php — the actual config tree; this is your source of truth for YAML keys.Resources/config/services.yaml — the service tag used to register custom checks.Check/ (or Checker/) — which built-in checks exist (DB, cache, Solr/Elasticsearch, disk, etc.).First real use case — point a Kubernetes readinessProbe (or your load balancer's target health check) at the endpoint. That is the whole reason to install this bundle; everything else is refinement.
Split liveness from readiness. A liveness probe should answer "is PHP-FPM alive?" and nothing else — it must never fail because Solr is slow. A readiness probe should exercise the full dependency graph. If the bundle exposes a single deep endpoint, add a trivial /ping route alongside it for liveness, and reserve the bundle endpoint for readiness.
Register a custom check when you have an app-specific dependency (S3 bucket reachability, an internal gRPC service, a queue depth threshold). Follow Symfony's autoconfigure pattern and confirm the exact tag name in Resources/config/services.yaml:
services:
App\Healthcheck\S3BucketCheck:
tags:
- { name: 'xrow.healthcheck', priority: 10 }
final class S3BucketCheck implements CheckInterface
{
public function check(): CheckResult
{
// return a status + human-readable message
}
}
Keep each check independently short-lived — see Gotchas.
Tune per environment. Disable expensive checks in dev so local page loads aren't slow, and leave them on in prod:
# config/packages/dev/xrow_healthcheck.yaml
xrow_healthcheck:
checks:
solr: false
disk: false
Deployment gating. Run the deep endpoint in CI after deploy and fail the pipeline on a non-2xx. This gives you a single, opinionated gate rather than hand-rolled curl scripts against three services:
curl --fail --retry 10 --retry-delay 5 --retry-connrefused https://staging-app.test/_health
Monitoring fan-in. The JSON response typically contains per-check status. Pipe it into your metrics/observability stack (Datadog, Prometheus blackbox exporter) so you get per-dependency alerting instead of one binary "site down" signal.
Bypass the firewall deliberately. Ibexa installs a security.yaml firewall that will intercept unauthenticated requests. Add an explicit access-control rule (and, in production, IP-allowlist it to the LB / k8s pod CIDR):
security:
access_control:
- { path: ^/_health, roles: PUBLIC_ACCESS, ips: ['10.0.0.0/8'] }
access_control returns a 302 redirect to login, which most probes interpret as healthy because it's not a 5xx. Assert on the body, not just the status code, or explicitly require 200.no-store, or route probes directly to the PHP backend.ping-only checks are useless. "Solr is up" is not "Solr has the correct core indexed". If your bundle only pings the port, layer a lightweight count/query check on top — a running but empty search backend is a very common silent outage.warning/info, otherwise your logs become unusable on the day you actually need them.readiness-checked while old pods are still serving. Make the check tolerate the pre-migration schema, or sequence migrations before the rollout.curl -i and inspect the JSON per-check payload first; then check var/log/dev.log with _profiler open in dev. If the response is opaque, look at the aggregator controller in Controller/ — it usually just iterates tagged services and concatenates results, so the check that's returning the bad status is easy to isolate by disabling checks one at a time in YAML.composer require xrow/healthcheck-bundle:^X.Y and read the diff on every upgrade — especially the Configuration.php tree, where new required keys are the most likely break.How can I help you explore Laravel packages today?