All posts

fundamentals

TCP, ICMP, and HTTP checks: which one to use when

Uptimera team7 min read

Every uptime monitor offers some mix of three check types — HTTP, TCP, and ICMP (ping). They're often listed as if interchangeable. They aren't. Each tests a different layer of the stack and catches a different class of failure. This post is about what each one actually verifies and which to reach for.

The OSI stack, briefly

Without going full networking textbook: when you load a webpage, the request traverses (from the bottom up) the physical network, IP routing, TCP, TLS, and HTTP. Each check type pokes at a different layer:

  • ICMP (ping) tests IP-level reachability — does my packet get to your host and back? Layer 3.
  • TCP tests transport — can I open a connection to a specific port? Layer 4.
  • HTTP tests application — does the service running on that port understand and serve requests? Layer 7.

Each layer can be healthy while the one above it is broken. ICMP succeeding doesn't mean the website works; HTTP succeeding doesn't mean it's serving the right content. Picking the right check means picking the layer you actually care about.

ICMP / ping checks: what they tell you

An ICMP echo ("ping") sends a tiny IP packet and waits for the host to reply. If it does, the host is reachable. If it doesn't, the host might be down — or your packet might be dropped by a firewall, or the host might be deprioritizing ICMP, or your route might have a problem unrelated to the host.

What ICMP is good for

  • Measuring round-trip network latency. The most accurate signal you can get without establishing a connection.
  • Detecting full network outages. ISP failures, BGP misroutes, regional connectivity events.
  • Checking servers that don't run a public TCP service. Internal hosts, network appliances, IoT gateways.

What ICMP is not good for

  • Detecting application failures. A crashed web server still pings — the machine is on.
  • Cloud-hosted services. AWS, GCP, and Cloudflare frequently drop or deprioritize ICMP. A ping monitor against an Application Load Balancer is meaningless.
  • Asymmetric routing problems. If the ping packet takes a different path than HTTP traffic, ICMP can succeed while real users fail.

TCP checks: confirming something is listening

A TCP check opens a connection to a specific port and immediately closes it. If the three-way handshake completes, the check passes. It doesn't send any payload; it doesn't care what application is on the other end. Just: is something willing to talk on this port?

What TCP is good for

  • Non-HTTP services. SSH (22), SMTP (25), PostgreSQL (5432), Redis (6379), custom binary protocols. Any TCP port your service exposes.
  • Confirming a load balancer is accepting connections before HTTP-level testing.
  • Detecting firewall and security group misconfigurations faster than HTTP, because TCP fails earlier in the stack.

What TCP is not good for

  • Application-level health. An nginx that's accepted the connection but can't reach its backend will still pass TCP. The pipe is open; the kitchen is on fire.
  • Stateful protocols. A plain TCP check against a database port confirms the port is open, not that the database accepts auth or is in a healthy state.

HTTP checks: the workhorse

An HTTP check completes a full request/response exchange: TCP handshake, TLS handshake (if HTTPS), request line + headers, response status, response body. It tests the entire stack — exactly what an end user does.

What HTTP is good for

  • Anything serving HTTP. Websites, REST APIs, webhooks, status pages, health endpoints.
  • Content-aware checks. A good HTTP monitor asserts response body content — the string "ok" appears, an expected JSON shape is returned, the page contains the right product name.
  • Response-time SLOs. The full response time (DNS + TCP + TLS + send + wait + receive) is the closest synthetic proxy for "how fast does a user experience this."
  • Authentication-aware monitoring. Send a header, hit a protected endpoint, verify the right response. The only check type that can do this.

HTTP's tradeoffs

  • More expensive to run. A TCP check is one round trip; an HTTPS check is at least three (TCP, TLS, request). This matters at high check frequency.
  • More moving parts to fail. DNS, TLS, app server, app code — any of them can fail an HTTP check. Good for detection, harder to read at a glance.

Picking the right check for the job

A practical decision tree:

  • It's a public web service or API: use HTTP. Always. The other types undercount real failures.
  • It's a non-HTTP TCP service (database, mail, SSH): use TCP — but pair it with an application-level health probe if you can (e.g. a PostgreSQL SELECT 1 via a sidecar).
  • It's a host with nothing listening, just network reachability: use ICMP. Network appliances, jump hosts, IoT gateways.
  • You're measuring network latency between regions: ICMP is the cleanest signal, but pair it with TCP/HTTP for context.

Combining check types intelligently

The most reliable monitoring stacks layer multiple check types on the same surface. A production-grade setup for a customer-facing API:

  • HTTP check on the public endpoint with content match — the primary signal. Page on failure.
  • TCP check on the load balancer port — a cheaper backup signal at higher frequency. Helps disambiguate "LB down" from "app down."
  • ICMP check on the underlying host (if accessible) — only useful when ICMP isn't firewalled. Helps disambiguate "network down" from "app down."

When all three fail simultaneously, you have a clear story: network outage or full host loss. When only HTTP fails, the application is the suspect. The layered approach turns a vague page into a quick triage.

Where to go from here

Audit your existing monitors and label each by check type. If any public web property is being monitored by ping alone, switch it to HTTP with a content match. If any database or non-HTTP service is being monitored by ping alone, add a TCP check. The improvements compound: clearer pages, faster triage, fewer false greens.