TCP Check
Synopsis
Director connects to one host's TCP port a number of times from where it runs, and writes the result of every check itself as an ECS document: the connection times, how many attempts were lost, and the state the port is in — up or down, since when, and after how many checks. Nothing is installed on the host.
The TCP Check is one of six service check devices, each checking one service: a Website, an HTTP Check, a TCP Check, a DNS Check, an ICMP Check, and a TLS Check. It is a client: the TCP device is a listener, which binds a port and receives what is sent to it.
One device, one service. A device checks one port, so every service checked has a row of its own in the fleet list, and the device's connection state says whether that service is up.
The results are the device's own. Every check writes a result, up or down, with no dataset assigned. A TCP Check has no datasets — see Service Check Datasets.
The device dials the port and binds nothing, so any number of TCP Checks may check port 443, and none blocks a listener on it. One Director owns each device.
The service check devices need Director 2.2.3 or later.
Schema
- id: <numeric>
name: <string>
description: <string>
type: tcp_check
tags: <string[]>
status: <boolean>
properties:
address: <string>
port: <numeric>
attempts: <numeric>
max_loss: <numeric>
interval: <numeric>
timeout: <numeric>
pipelines: <pipeline[]>
Configuration
The following fields are used to define the device:
Device
| Field | Required | Default | Description |
|---|---|---|---|
id | Y | - | Unique numeric identifier |
name | Y | - | Device name |
description | N | - | Optional description |
type | Y | - | Must be tcp_check |
tags | N | - | Optional tags |
status | N | true | Enable/disable the device |
Target
| Field | Required | Default | Description |
|---|---|---|---|
address | Y | - | A host name or an IP address — not a wildcard, a URL, or host:port. An IPv6 address as it is, or in one pair of brackets |
port | Y | - | The port the check connects to, from 1 to 65535. The device dials it: it binds nothing |
Pipeline
The device takes at most one pre-processing pipeline of its own: the device's pipeline picker in the console, pipelines: in a configuration file. Its results go through it, and through none when the device has none.
Datasets
A TCP Check has no datasets: it writes its results directly. Traceroute is a website's dataset alone: one still assigned to the device is left out with a warning in the device's log, and the device writes its results as before.
Advanced Configuration
| Field | Required | Default | Description |
|---|---|---|---|
attempts | N | 10 | Connects a check makes, a second apart from start to start, from 1 to 100 |
max_loss | N | 50 | The share of the attempts, in percent, that may fail while the port is up, from 0 to 99 |
interval | N | 60 | Seconds between checks: a result every interval. At least 10 |
timeout | N | 2 | Seconds each connect may take, from 1 to 120 |
A configuration error stops the device with Configuration error, and the message names the property. A number is read whole: a fraction, or one no 32-bit integer holds, is refused, never converted.
How a Check Works
A name is resolved once a check, and every connect goes to its first address, so the connect time is the connection's alone. Each connect is closed as soon as it is made: the service sees a connection opened and closed, which it may log.
A check takes at least attempts - 1 seconds, and up to attempts × timeout when every attempt waits its timeout out. One longer than its interval delays the next, which starts a second after it ends.
The check is up when at most max_loss percent of its connects failed. Otherwise it is down, and error.type says why:
error.type | When |
|---|---|
dns | The name does not resolve: no connect was made |
connection, timeout | Every connect failed |
loss | Some connects went through, but more than max_loss percent failed |
A host whose name does not resolve made no connect: its result has no attempt and no loss.
Results and State
Every check writes one result, with event.dataset tcp_check and definition id 12151, to the metric table:
destination.address,ip,port;network.transport.service_check.tcp.attempts,succeeded,loss.pct(a fraction of 1),rtt.connect.min,avg,max, andresolve(the name's lookup).
Every result carries the state the port is in, under state.*. A TCP Check found up at 12:01, checked every minute since 09:15, and found down at 12:02 writes:
"state": {"id": "512300181-1a0e74bce20", "status": "up", "started_at": "2026-09-28T09:15:00Z",
"duration_ms": 9960000, "checks": 167, "up": 167, "down": 0, "changed": false}
"state": {"id": "512300181-1a0e7e4b2c0", "status": "down", "started_at": "2026-09-28T12:02:00Z",
"duration_ms": 0, "checks": 1, "up": 0, "down": 1, "changed": true,
"previous": {"status": "up", "duration_ms": 10020000}}
For the state's fields, how to alert on it, and the fields every record carries, see Results and State.
Connection States
| State | When |
|---|---|
| Connected | The port is up: db01.example.com:5432 is up |
| Connection error | It does not answer, its name does not resolve, or too many of its attempts failed |
| Configuration error | A configuration that does not validate |
The message says what the check ran into (db01.example.com:5432 is down: connect: connection refused), in words that stay the same while the failure does, so the state moves only when the service's does.
Console
In the console, go to
General settings , as on every device, with the device's pre-processing pipeline.Check settings :Address andPort .Advanced settings :Interval ,Timeout ,Attempts , andMaximum loss .Review and create .
There is no
Simulation
The TCP Check is not simulated. What it writes is what its check finds, with the state the port is in, which one generic sample cannot stand in for.
Examples
Checking a PostgreSQL port every minute, with five connects a check of which at most one may fail... | |