Most uptime monitoring is HTTP monitoring: send a request to a URL, judge the response. That works for anything that serves web pages or APIs. It does nothing for the Postgres server on port 5432, the SMTP relay on 587, the SSH bastion, the Redis instance, or the message broker your workers depend on. None of those speak HTTP, and all of them can take your product down without a single web page going dark.
A TCP port monitor covers that gap. It is also the check type most often set up with the wrong expectations, so this post is about what it actually measures, when to use it instead of (or alongside) an HTTP check, and what neither one can see.
The one thing a TCP check does
It opens a connection to a host and port and reports up if the connection completes inside the timeout. That is the whole test. On RealUptime a TCP monitor sends no bytes after the handshake and reads none back. It never speaks the protocol on the other end, never authenticates, never touches data.
So "up" means: the host is reachable from the probe region, something is listening on that port, and the operating system accepted the connection. "Down" means one of a refused connection, an unreachable host, or a connection that did not complete in time.
Everything else works like an HTTP monitor. The check runs from the four core regions by default (Virginia, California, Frankfurt, Tokyo), or from your pick of the ten live regions on paid plans, on the interval you chose. Connect time is recorded per region, so latency charts and history bars fill in the same way. A region needs two consecutive failures before it flips to down, and a state change fires the same alert fan-out: incidents, status page components, subscriber email, Slack, PagerDuty, webhooks.
What it proves
More than it might seem.
- The network path works. DNS resolved, routing got there, no firewall dropped the packet. For a database on a private host reachable only through a specific address, this is most of what you want to know.
- The process is running and accepting. A crashed database does not listen. A database that is up but has exhausted its connection slots still accepts the TCP handshake and then refuses at the protocol layer, which a TCP check will not see, and which brings us to the limits.
- Per-region reachability. Because the check runs from several places, a firewall rule that blocks one cloud provider's range, or a route that breaks between Europe and your host, shows up as one region down while the others stay green. That is a different fault from "the service is down," and the per-region view is what separates them.
What it does not prove
- That the service works. Accepting a connection is not the same as answering a query. A Postgres server in recovery, a Redis instance that is out of memory and rejecting writes, an SMTP server that greets you and then refuses to relay: all accept the handshake. A TCP monitor is a reachability check, not a functional check. If you need "can it do its job," you need something that speaks the protocol, either an HTTP endpoint in your own app that runs a real query, or a heartbeat from a job that exercises the service and pings only on success.
- That the right thing is listening. Port 5432 answering proves something accepted a connection on 5432. If a deploy left a stale process there, the check is green and the app is broken.
- Anything about the data. By design. A monitor that reads your database traffic is a monitor you have to trust with your database traffic. Connect-and-close means there is nothing to trust it with.
The TLS option, and the deliberate choice inside it
Turning on TLS adds a handshake to the success condition and starts reading the certificate the server presents. Expiry alerts then work exactly as for an HTTPS monitor: 30, 14, 7 and 1 days before the certificate lapses, with the remaining days shown on the monitor.
There is one decision in there worth understanding. The up/down result depends on the TLS handshake completing, not on the certificate chaining to a public authority or matching the hostname. Databases and internal brokers routinely present private or self-signed certificates. Reporting a healthy database as down because it was signed by your own CA would be a false alarm, and false alarms are what teach people to ignore monitors. The expiry date is still read and still alerted on, because that is the part you need to act on.
If you do need "the certificate is publicly valid," that is an HTTPS monitor's job, and for a public-facing endpoint you should have one.
Choosing between TCP and HTTP
A short table, since this is the decision most people are really making:
| The thing | Check type | Why |
|---|---|---|
| Public website, API, login page | HTTP | You want status code, response time, and optionally a body assertion |
| Postgres, MySQL, Redis, brokers | TCP (TLS if enabled) | No HTTP endpoint; reachability and expiry are the useful signals |
| SMTP, IMAP | TCP with TLS | Same, plus certificate expiry on mail is a classic silent failure |
| SSH bastion | TCP | Proves the door is open; nothing else should be exposed |
| A service behind a private CA | TCP with TLS | Handshake proves listening; expiry tracked; validity not judged |
| "Does the app actually work" | HTTP against a real endpoint, or a heartbeat | TCP cannot answer this |
The pattern that works for most small teams: an HTTP check on every customer-facing surface, a TCP check on every dependency the app cannot live without, and a heartbeat on every scheduled job. Three check types, three different questions, no overlap.
Two mistakes we see
Monitoring the load balancer's port and calling the database monitored. The load balancer accepts connections regardless of what is behind it. Point the TCP check at the thing you actually care about, or at the closest address that would refuse if it died.
Exposing a port to the internet so a monitor can reach it. Do not open 5432 to the world for the sake of a check. If a dependency is not reachable from outside, monitor it from inside: a heartbeat job on a host that can reach it, pinging on success, gives you the same "it stopped working" signal without a new attack surface. The TCP check is for things that are already meant to be reachable from where the probes run.
Where to start
TCP monitors are part of the free tier, from the four core regions, with TLS and expiry tracking included. Full details, including exactly what counts as up, are in the TCP monitor docs. If the only thing you have monitored so far is the homepage, the database behind it is a good second monitor to add, and it takes about the same minute.