Independent comparison · no paid rankings
Home / Blog / Health checks: tell an open port from a healthy application
Technical

Health checks: tell an open port from a healthy application

Open TCP 443 and a live PHP process do not guarantee the app can serve an order or reach its database. A useful health check tests what the user expects.

5 min read Updated Jul 19, 2026

The load balancer marks the backend "healthy": port 443 responds. Meanwhile PostgreSQL refuses connections — every API request returns 503. Users see an outage; host monitoring shows green. The team loses twenty minutes hunting "network" when the health check never tested the database.

This scenario repeats weekly on stacks that look well configured: valid TLS certificate, active web process, TCP probe passing. The problem is not the host — it is the question asked by the probe.

An application health check answers a precise question: can this instance handle a representative request right now? Not: is someone listening on a port? The distinction changes everything when a critical dependency fails without stopping the web server.

TCP, shallow HTTP and deep check

Teams often hesitate between three probe levels. Each has its place — but only the third protects the end user.

TypeChecksLimit
TCP connectProcess listeningFast, blind
HTTP 200 /Home pageMay be CDN-cached
HTTP /health/liveProcess + runtimeMinimal
HTTP /health/readyDB, cache, depsRemove traffic if fail

/health/live serves liveness (Kubernetes): no database — avoids crashloop when Postgres is down but the application still runs. /health/ready serves readiness: critical dependencies only — database, cache, queue if essential.

A check that passes when DB is dead sends traffic into a void. This is the most frustrating case: all green on infra, all red for the client.

Design fast reliable checks

A good health endpoint follows four rules. First, a timeout under 1–2 seconds, aligned between load balancer and kubelet — a slow check delays traffic removal when you need it most.

Second, no side effects: no test order creation in production, no email send, no database write. The probe reads state; it does not modify it.

Third, a stable JSON response: { "status": "ok", "checks": { "db": "ok" } } — parseable by monitoring and readable by a human during an incident.

Finally, a 2–5 second cache in memory if probes are aggressive. Avoid reusing a heavy page (WordPress admin, full dashboard) as probe: you waste CPU on every poll.

Host LB, Kubernetes and shared hosting

OVHcloud, Hetzner and Scaleway offer load balancers with configurable HTTP probes. Set the check on /health/ready, a reasonable interval (5–10 seconds) and consecutive up/down thresholds to avoid flapping.

On Kubernetes, align probe paths with the external load balancer — inconsistent double checking causes permanent healthy/unhealthy toggling.

On shared hosting without custom probes, monitor an external URL (UptimeRobot, etc.) with alerts. This is a complement, not a substitute for an internal probe testing dependencies.

Security and information leak

A public /health listing versions, environment and cluster name is an invitation. Rate-limit, internal network, IP allowlist. In sensitive infrastructure, mTLS between load balancer and application.

An attacker probing /health sometimes discovers database state, framework version or internal topology — useful information for a targeted attack.

The climax: green on monitoring, red for the customer

The probe must match minimal user journey — not transport layer.

Decide and move forward without blind spots

Implement separate live and ready endpoints, each with a clear responsibility: the first decides whether the process should restart, the second whether the instance can receive traffic. Include only critical dependencies in ready — not the full business stack. Secure the endpoint on internal network or IP allowlist. Align load balancer and Kubernetes on same paths and thresholds. Validate in staging: cut DB → traffic removed without mass pod restart. Compare load balancer offers via the directory and compare tool.

Frequently asked questions

Why is TCP on port 80 rarely enough?

A TCP check only verifies a socket is open — not that the application responds correctly, nor that the database is reachable. The port can be open while PHP-FPM is saturated, the app returns 500 errors or PostgreSQL refuses connections. During an incident, you waste time diagnosing "network" when the problem is application-level.

What should /health/ready contain?

Light checks of critical dependencies: database ping, Redis PING, queue if essential — without running full business logic. Timeout should stay short (1–2 seconds). On failure, the instance is removed from traffic; it is not necessarily restarted, which avoids worsening a database incident.

Public or internal health check?

Prefer an internal endpoint — private network, IP allowlist or mutual authentication. Public unauthenticated /health can become an attacker probe or information leak (software version, database state). If a public endpoint is unavoidable, limit exposed information and apply strict rate-limiting.

How to avoid overloading the app?

Cache the result a few seconds in memory, limit parallel checks and use a dedicated lightweight endpoint without verbose logs. On shared hosting, a load balancer probing every second multiplies load — configure a 5–10 second interval and a light endpoint.


Healthy means "ready to serve" — not "telnet gets a response on the port".

Compare European hosts

Filter by compliance, location and use case — then open the sheets to verify the real scope.

Browse the directory
Blog

Related reading

All articles →