TCP Port Monitoring

Monitor any host and port, and assert on what answers

Databases, message queues, mail servers, custom services. A TCP monitor connects to host:port from 22 public locations or inside your own network, optionally sends data, and asserts on the response and the response time. Defined in TypeScript, deployed from CI, alerting built in.

postgres.check.ts
1// postgres.check.ts
2import { TcpMonitor, TcpAssertionBuilder, Frequency } from 'checkly/constructs'
3
4new TcpMonitor('postgres-primary', {
5 name: 'Postgres primary',
6 frequency: Frequency.EVERY_30S,
7 locations: ['us-east-1', 'eu-west-1', 'ap-southeast-1'],
8 // Warn at 1s, fail at 3s
9 degradedResponseTime: 1000,
10 maxResponseTime: 3000,
11 request: {
12 hostname: 'db.acme.dev',
13 port: 5432,
14 ipFamily: 'IPv4',
15 assertions: [
16 TcpAssertionBuilder.responseTime().lessThan(1000),
17 ],
18 },
19})

Trusted by teams whose infrastructure is more than HTTP

Vercel
Carhartt
CrowdStrike
Airbus
Fanatics
Mistral
ServiceNow
GoFundMe
Hopper
1Password
Fastly
Total Wine
“TCP checks are working nicely for our use case. We're using them to monitor some of our critical network services.”
Matt Watkins·Release Engineering Team, The Linux Foundation

An open port tells you the socket is up. Not that the service is.

Most port checks stop at the handshake. Checkly TCP monitors finish the conversation: send the payload your service expects, assert on the reply, and time each phase of the connection from every location you run it in.

responseData().contains()

A connection is not enough

A port that accepts a SYN can still be a dead service. Send a payload after the handshake and assert on what comes back: a PONG, a 220 banner, your own health string.

dns · connect · data

Latency, split into phases

Every run records DNS lookup, TCP connect, and data transfer separately, per location. Degrade at one threshold, fail at another, and see which phase moved.

privateLocations: [...]

Public edge or inside the VPC

Run from 22 public locations, or from a Checkly Agent inside your own network for the databases and brokers that were never meant to face the internet.

Monitor the infrastructure behind your endpoints

Your API monitor can pass while the database it depends on is refusing connections from half the world. Put a TCP monitor on every port your application needs and find out first.

5432330627017

Databases

Confirm Postgres, MySQL, or MongoDB accepts connections from outside the app tier, and how long the handshake takes from each region.

637956729092

Caches and message queues

Send PING to Redis and assert on PONG. Verify RabbitMQ or Kafka brokers are listening before the consumers start timing out.

587465993

Mail servers

Open SMTP submission or IMAPS, assert the 220 greeting arrives, and watch response time so a slow relay is caught before the queue backs up.

any port

Custom TCP services

Anything that speaks a line protocol. Send your own health-check payload and assert the response contains what your service should say.

should fail

Firewall and network rules

Flip "this request should fail" and a refused connection passes. Prove a port that must stay closed to the public still is, from 22 vantage points.

private location

Internal services

Run the same monitor on a Checkly Agent inside your VPC to reach hosts that are not exposed to the internet at all.

One honest limit: some public locations run on AWS, which blocks outbound port 25. Monitor SMTP on 587 or 465, or run the monitor from a private location. For plain host reachability and packet loss, Checkly also has ICMP ping monitors.

Define, test, deploy. TCP monitoring as code

The monitor is a TypeScript construct in your repo. Test it from CI, preview the deploy, apply it. Terraform and Pulumi providers cover the teams that live there instead.

01

Define the monitor in TypeScript

A TcpMonitor construct takes a hostname, a port, optional data to send, and assertions on response time and response data. Set degraded and failure thresholds, pick locations or a private location, and add alert channels. It lives in your repo next to the service it watches.

smtp.check.ts
1// smtp.check.ts
2import { TcpMonitor, TcpAssertionBuilder } from 'checkly/constructs'
3
4new TcpMonitor('smtp-relay', {
5 name: 'SMTP relay',
6 request: {
7 hostname: 'mail.acme.dev',
8 port: 587,
9 // Sent after the connection is established
10 data: 'EHLO checkly\r\n',
11 assertions: [
12 // The server greets, then acknowledges EHLO
13 TcpAssertionBuilder.responseData().contains('220'),
14 TcpAssertionBuilder.responseData().contains('250'),
15 TcpAssertionBuilder.responseTime().lessThan(1500),
16 ],
17 },
18})
02

Test it from CI

npx checkly test runs the monitor once from a Checkly location and reports pass or fail in the terminal. Put it in the pipeline that ships your infrastructure change and a broken port fails the build, not the on-call.

npx checkly test
$ npx checkly test
 
Running 2 checks in eu-west-1.
 
src/__checks__/postgres.check.ts
  ✔ Postgres primary (86ms)
src/__checks__/smtp.check.ts
  ✔ SMTP relay (241ms)
 
2 passed, 2 total
03

Deploy for continuous monitoring

deploy --preview shows exactly what will be created, updated, or deleted. deploy applies it. From then on the monitor runs on its schedule, retries on failure, and pages the channels you attached.

npx checkly deploy
$ npx checkly deploy --preview
 
Create:
    TcpMonitor: postgres-primary
    TcpMonitor: smtp-relay
 
$ npx checkly deploy

Priced per monitor, not per run

TCP monitors are uptime monitors: 10 included on Hobby, 50 on Starter, 75 on Team, more in blocks of 25. A 30-second schedule costs the same as a daily one. See pricing.

every 10s to 24h22 public locationsprivate locationsfull parity in the app

Put a monitor on every port that matters

Write one TcpMonitor construct, run it from CI, deploy it. The next time a database stops accepting connections, you will know before the API errors do.

No credit card required.