What is Health Check?
A periodic test, such as an HTTP request or a command, that tells an orchestrator or monitor whether a service is working.
Definition
A health check is a small, repeatable test that a platform or monitoring tool runs against a service to decide whether it is working, and what to do if it is not. It can be an HTTP request to an endpoint such as /healthz, a TCP connection, a gRPC health call or a command run inside the container, and it passes or fails based on rules like the status code, response time or exit code. Orchestrators act on the result automatically. Docker's HEALTHCHECK instruction gives a container a health status of starting, healthy or unhealthy, with defaults of a 30-second interval, a 30-second timeout and 3 retries before the container is marked unhealthy. Kubernetes splits the idea into three probes run by the kubelet: a startup probe that holds off other checks until the app has started, a liveness probe whose repeated failure restarts the container, and a readiness probe whose failure removes the Pod from Service endpoints so it stops receiving traffic. External uptime monitors such as Uptime Kuma and Gatus run the same kind of checks from outside and send alerts instead of restarting anything.
When to Use Health Check
Keep liveness checks cheap and local to the process: they should answer 'is this process stuck?' and not depend on databases or other services, otherwise one slow dependency can make Kubernetes restart every replica at once. Put dependency checks in readiness, where failure only stops traffic. Use a startup probe or a start period for slow-booting apps instead of a long initial delay. Exposing a health endpoint publicly can leak version or dependency details, so return minimal information.
Health Check in Practice
- A Dockerfile adds HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost/ || exit 1, so docker ps shows the container as unhealthy when the web server stops answering.
- A Kubernetes Deployment uses a readiness probe on /ready that fails while caches warm up, so traffic only reaches the Pod once it can serve requests, and a separate liveness probe on /healthz to recover from deadlocks.
- Gatus checks https://api.example.com/health every minute with conditions [STATUS] == 200 and [RESPONSE_TIME] < 300 and posts to Slack after three consecutive failures.
Common Mistakes
- Making the liveness probe call the database, so a database outage triggers restarts across every Pod and turns a partial outage into a full one.
- Using the same endpoint and thresholds for liveness and readiness, which removes the ability to stop traffic without restarting.
- Setting timeouts or failure thresholds so tight that a busy but healthy service is restarted under load, causing cascading failures.
- Relying only on in-cluster probes; they cannot tell you that DNS, the load balancer or TLS certificates are broken from the user's side, which external monitoring catches.

