TCP monitoring checks that a port is open and a service accepts connections. It's not HTTP (which sends a request and waits for response) — it's pure socket connection: if the connection succeeds, the port works; if it fails, the port is closed or the service is down.
For web applications, HTTP monitoring is enough. But if you have a database, cache, mail server, or any non-HTTP service — TCP check is essential. You can't monitor PostgreSQL with HTTP requests (SQL doesn't understand HTTP). You have to drop down to the TCP level.
When HTTP Monitoring Isn't Enough
Database Servers (PostgreSQL, MySQL, MongoDB)
Databases don't listen on HTTP (typically). PostgreSQL listens on port 5432 and expects PostgreSQL wire protocol. MySQL listens on 3306. MongoDB listens on 27017. If you try to send an HTTP request — the server will reject it immediately. The only way to check if it's alive is to open a socket connection.
Cache Systems (Redis, Memcached)
Redis listens on port 6379 and expects RESP protocol (Redis Serialization Protocol). Memcached listens on 11211. You could send a PING command and get +PONG, but that requires protocol knowledge. TCP monitoring is sufficient for basic checks.
Mail Servers (SMTP, IMAP, POP3)
SMTP listens on port 25 or 587. IMAP listens on 143 or 993 (SSL). POP3 listens on 110 or 995 (SSL). When you connect via TCP — the server immediately sends a greeting banner (220 mail.example.com ESMTP). TCP connection proves the server is responding.
Game Servers and Custom Protocols
Minecraft server, Discord bot, proprietary application backend — all listen on custom ports and expect custom protocols. HTTP monitoring is useless here. TCP check is the only way to verify basic connectivity.
Internal Services Not Over HTTP
A microservice might listen on gRPC (port 50051), not HTTP. Or use raw TCP for performance. TCP check detects this, HTTP health check won't help.
How TCP Health Check Works
TCP Three-Way Handshake
Step 1: SYN
Monitor sends SYN (synchronization) packet to target IP:port with SYN flag
Step 2: SYN-ACK
Server responds with packet with SYN and ACK (acknowledgement) flags, confirming it received our SYN
Step 3: ACK
Monitor sends ACK packet to confirm it received the SYN-ACK
Result: connection established, port is open
Possible Outcomes
✓ SUCCESS (port open): TCP handshake completed, connection open. Service is listening.
✗ TIMEOUT (connection refused): server doesn't respond to SYN. Port is closed or service not running.
✗ RST (reset): server received SYN and explicitly sent RST (reset). Active rejection, usually means wrong port or service not on this machine.
✗ FIREWALL BLOCK: packet is dropped, timeout occurs. Firewall may block, or IP not routable.
Common Ports to Monitor
Databases
PostgreSQL: 5432 (default)
MySQL: 3306 (default)
MongoDB: 27017 (default)
Oracle: 1521 (default)
SQL Server (MSSQL): 1433 (default)
MariaDB: 3306 (same as MySQL)
Cache and Memory Stores
Redis: 6379 (default)
Memcached: 11211 (default)
Redis Cluster: 6379-6384 (nodes)
Email Services
SMTP (unencrypted): 25
SMTP (TLS): 587, 465
IMAP (unencrypted): 143
IMAP (SSL/TLS): 993
POP3 (unencrypted): 110
POP3 (SSL/TLS): 995
Search and Analytics
Elasticsearch: 9200 (HTTP), 9300 (node communication)
Solr: 8983 (default)
OpenSearch: 9200 (same as Elasticsearch)
Message Queues
RabbitMQ: 5672 (AMQP), 15672 (HTTP management)
Kafka: 9092 (default broker port)
NATS: 4222 (default)
Other Services
SSH: 22
DNS: 53
VNC (remote desktop): 5900
RDP (Windows remote): 3389
LDAP: 389 (unencrypted), 636 (SSL)
TCP Connection Latency
Connection time for TCP handshake is a valuable metric. If it's normally 5ms and now 500ms — the service is overloaded or network is slow.
< 50ms: fast, service is local or on fast network
50-200ms: normal, service is in different datacenter or region
200-1000ms: slow, may be network issues or overload
1000ms+: very slow, critical problem or misconfiguration
TLS on TCP: Monitoring SSL/TLS Connections
Many services use TLS encryption on top of TCP (TCP + TLS). MySQL can be configured with TLS, SMTP requires TLS (port 587/465), Redis can use TLS.
TCP vs TLS Monitoring
TCP check only: verifies port is open. Doesn't check TLS.
TLS check: verifies TCP connection opens, then checks TLS handshake, and extracts certificate information (expiry, issuer, domain).
Recommendation: for TLS services use TLS check, not plain TCP. This catches certificate expiry.
Example: Monitoring PostgreSQL with TLS
PostgreSQL can be configured to require TLS. Client sends sslmode=require in connection string.
For monitoring: use TLS check (not just TCP) on port 5432 with TLS enabled.
This catches when certificate expires or when TLS handshake fails.
TCP Monitoring in AtomPing
Creating a TCP Check
Type: TCP
Host: db.example.com (or IP)
Port: 5432 (PostgreSQL)
Timeout: 10 seconds (enough for handshake)
Interval: 60 seconds
Regions: select multiple for geographically distributed checks
Combining TCP and HTTP Monitoring
For critical services, monitor both TCP and HTTP:
TCP check (port open?): simple, fast, if it fails — service is completely down
HTTP check (service responds correctly?): detailed, catches application errors, returns 500
Interpretation:
- ✓ TCP pass, ✓ HTTP pass → normal
- ✓ TCP pass, ✗ HTTP fail → application problem (process running, logic broken)
- ✗ TCP fail, - HTTP skip → network/infrastructure problem (port closed/firewall)
Common TCP Monitoring Mistakes
Mistake 1: Monitoring Wrong Port
ps aux | grep postgres shows the process but not the port. Check the config:
# PostgreSQL
grep port /etc/postgresql/*/main/postgresql.conf
# MySQL
grep port /etc/mysql/my.cnf
# Redis
grep port /etc/redis/redis.conf
# Or use netstat/ss
ss -tlnp | grep postgres Mistake 2: Firewall Blocks Monitor
TCP check returns timeout, but service responds locally. Reason: firewall blocks incoming connections from monitor IP.
Solution: open ports in firewall for monitor IPs (or IP range, if monitors are distributed).
Mistake 3: Service Listens Only on Localhost
Service is configured to listen on 127.0.0.1:5432 (localhost), not 0.0.0.0:5432 (all interfaces). External monitor can't connect.
Solution: configure service to listen on all interfaces or public IP. Or use internal monitor (from same machine or VPC).
Mistake 4: Database Requires Authentication
PostgreSQL/MySQL will open TCP connection but then require password. TCP check passes (connection open), but if you need credentials for real checks — use service-specific check.
Alternative: create read-only query in database and use health endpoint instead of direct database check.
Mistake 5: Too Aggressive Monitoring
If 100 monitors open connections to database every 5 seconds — that's 2000 connections per minute. First it overloads connection pool, then database crashes.
Solution: monitor less frequently (every 60 seconds), or use only 3-5 monitors in different regions, not all 100.
Monitoring Internal Services
If database is inside VPC and not accessible from internet — use internal monitor (agent/worker inside VPC) for TCP checks.
Option 1: deploy agent in same VPC so it can reach the database
Option 2: expose health endpoint to external world (with auth), monitor HTTP instead of TCP
Option 3: use bastion host/jumpbox and proxy monitoring through it
Combining TCP with Complete Monitoring Strategy
TCP check alone is insufficient. For production-critical services use a multi-layered approach:
Layer 1: TCP check (is port responding?) — fast, basic connectivity
Layer 2: Health endpoint (is service healthy?) — detailed status information
Layer 3: Synthetic transactions (can I actually use it?) — test real workflow (query for DB, charge for payment API)
Layer 4: Internal monitoring (logs, metrics, tracing) — context and root cause
TCP Monitoring vs ICMP Ping
Often confused: TCP check and ICMP ping (ICMP monitoring).
ICMP ping: checks if host is reachable (is machine accessible on network). Doesn't check specific service.
TCP port check: checks if specific service (port) accepts connections. More specific.
Recommendation: for critical services use TCP (catches service failures), not ICMP (only catches network failures).
TCP Port Monitoring Checklist
Service: is the port where service listens correctly identified?
Firewall: is port open for monitor (or firewall allows from external)?
Network: does service listen on all interfaces (0.0.0.0), not just localhost?
TLS: if service uses TLS, use TLS check, not TCP
Load: does monitoring overload service with frequent connections?
Combination: TCP + HTTP checks for defense-in-depth
Interpretation: correctly interpreting results (TCP pass ≠ service is healthy)
Related Articles
Complete Guide to Uptime Monitoring — overview of all check types
Health Check Endpoint Design — TCP alternative for HTTP services
SSL Certificate Monitoring — TLS checks for encrypted services
ICMP Ping Monitoring — network-level checks
TCP Check — in AtomPing
FAQ
What is TCP port monitoring?
TCP port monitoring checks whether a specific service is listening and accepting connections on a given port. Unlike HTTP monitoring (which sends an HTTP request), TCP monitoring simply attempts to open a socket connection and checks if the server responds. It works with any service: databases (PostgreSQL port 5432), cache systems (Redis 6379), mail servers (SMTP 25), or custom protocols. If the connection succeeds, the service is reachable.
How is TCP monitoring different from HTTP monitoring?
HTTP monitoring sends a complete HTTP request and checks the response status, content, and headers. TCP monitoring only checks if the port accepts connections (TCP handshake completes). TCP is lighter-weight and works with non-HTTP services (databases, game servers, raw sockets). HTTP provides more detail about service health. Use TCP for services that don't speak HTTP, use HTTP for web APIs.
What are common ports to monitor?
PostgreSQL: 5432. MySQL: 3306. Redis: 6379. MongoDB: 27017. Elasticsearch: 9200. SMTP (mail): 25 or 587. IMAP (mail): 143 or 993 (SSL). SSH: 22. DNS: 53. RDP (Windows remote): 3389. Game servers typically use custom ports. Don't monitor privileged ports below 1024 from untrusted networks. Focus on application-critical services.
How does a TCP connection check work?
TCP handshake: 1) Client sends SYN (synchronization) packet. 2) Server responds with SYN-ACK. 3) Client sends ACK (acknowledgement) back. If all three succeed within timeout, the port is open. If server doesn't respond (timeout) or rejects the connection (RST), the port is closed or the service is down. Connection time is latency metric — slow opens indicate network or server load issues.
How do you combine TCP and HTTP monitoring for full coverage?
Monitor critical services with both: TCP check (is the port accepting connections? detects complete failures), and HTTP check (is the service responding correctly? detects application errors). If TCP passes but HTTP fails, the service is running but unhealthy. If TCP fails but HTTP passes (rare), network/firewall issue between monitor and service. Together they provide defense-in-depth.
What are the limitations of TCP monitoring?
TCP only checks connectivity, not service health. A database might have an open port but be out of memory. A web server might accept TCP connections but return 503 errors. Redis might respond to TCP ping but have insufficient memory. Use TCP for basic 'is it running?' checks. For detailed health, pair with service-specific checks (SQL queries for DB, HTTP requests for web, specific commands for cache).