Active monitors
Unlike heartbeat, where your service “calls” Notifly, an active monitor works the other way: a Notifly serverless function itself polls the specified resource every N seconds. If a configured number of attempts in a row fail, an alert is sent; when the connection is restored, a recovery is sent.
There are 26 supported check types — from a simple HTTP GET to lightweight
protocol handshakes for mail, databases, queues and network services,
DNS resolution and TLS certificate expiry checks.
Basic checks:
kind | What it checks | Target format |
|---|---|---|
http | GET <url>, expects 2xx (or expectedStatus) | https://example.com/health |
tcp | TCP handshake — port is open | host:port |
tls | TCP+TLS handshake; expectedStatus = minimum certificate validity buffer (days) | host:port |
dns | Resolve a name using the system or specified resolver | example.com or example.com@8.8.8.8:53 |
Protocol handshakes (target is always host:port):
kind | What it checks |
|---|---|
smtp | TCP, read 220 banner, send EHLO/QUIT |
imap | TCP, wait for * OK ..., send a LOGOUT |
pop3 | TCP, wait for +OK ..., send QUIT |
ssh | TCP, read SSH-... banner |
ftp | TCP, wait for 220 banner, send QUIT |
redis | TCP, send PING, expect +PONG |
postgres | TCP, send StartupMessage, expect R/E/N |
mysql | TCP, read handshake packet (protocol_version=10) |
mongodb | TCP, send hello (OP_MSG), expect a response |
memcached | TCP memcached check |
clickhouse | TCP ClickHouse check |
cassandra | TCP Cassandra check |
zookeeper | TCP ZooKeeper check |
mqtt | TCP MQTT broker check |
kafka | TCP Kafka check |
amqp | TCP AMQP / RabbitMQ check |
nats | TCP, wait for INFO ... banner |
ldap | TCP, send SearchRequest, expect a response |
rdp | TCP, send X.224 Connection Request, expect a response |
sip | UDP, OPTIONS (default port :5060) |
ntp | UDP, NTP request (default port :123) |
snmp | UDP, SNMPv1 GetRequest (default port :161) |
All TLS variants are performed over regular TCP (without StartTLS), so for encrypted ports specify the already-encrypted port (
smtp→:465,imap→:993,pop3→:995,redis→:6380, etc.). To check plain TCP connectivity itself — usekind: "tcp".
How it works
Section titled “How it works”every minute: timer-trigger → notifly-monitor └─▶ SELECT WHERE next_check_at <= now AND status != "paused" └─▶ HTTP GET / TCP Dial with timeoutSec ├─ success → status=up, fail_count=0 │ if it was "down" and recoveryMessage exists → recovery └─ failure → fail_count++; if ≥ consecutiveFails and not "down": send alert, status=down- Storage —
monitorstable in YDB Serverless, indexed bynext_check_at. - Check — a separate Cloud Function
notifly-monitor, triggered by a Yandex Cloud timer (cron* * * * ? *— once per minute). - Notification — a normal Notifly message is sent via the channel chosen when creating the monitor and reaches all your clients (web, Android, desktop) like any other push notification.
Events
Section titled “Events”Since Notifly initiates the communication, there are two explicit events:
| Event | When sent | Text |
|---|---|---|
| Loss of connectivity (alert) | After consecutiveFails consecutive failures, only on the first transition to down. The message includes the technical error (e.g. dial tcp: connect: connection refused) | alertMessage |
| Recovery (recovery) | On the first successful check after being down, only if recoveryMessage is set | recoveryMessage |
There will be no repeated alert spam: while the monitor is down, no new messages are sent, checks continue at the usual interval and simply record the status.
Creating a monitor
Section titled “Creating a monitor”Through the admin UI
Section titled “Through the admin UI”- Open app.notifly.ru → Monitors.
- Click “Create monitor”, fill in:
- Name — for display, e.g. “Prod site” or “Postgres replica”.
- Channel — which channel to send the notification through.
- Check type — one of the 26 supported
kindvalues (see tables above). - Target — format depends on the type: URL,
host:portor DNS name. - Period (sec) — between checks (minimum 30, maximum 86400).
- Timeout (sec) — how long to wait for a response in one attempt (default 10, maximum 30).
- Consecutive fails — how many consecutive failed checks before an alert (default 1; typically 2–3 to avoid reacting to single network jitters).
- Expected HTTP status (only
http) —0means “any 2xx”, otherwise a specific code (e.g.200). - Certificate buffer, days (only
tls) —0= do not check;30= alert 30 days before expiry. - Alert / recovery message — text that will appear in the push.
Via REST API
Section titled “Via REST API”# HTTP checkcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "appid": 12345, "name": "Прод-сайт", "kind": "http", "target": "https://example.com/health", "intervalSec": 60, "timeoutSec": 10, "expectedStatus": 0, "consecutiveFails": 2, "alertMessage": "Сайт недоступен!", "alertPriority": 9, "recoveryMessage": "Сайт снова отвечает." }'
# TCP checkcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "appid": 12345, "name": "Postgres-реплика", "kind": "tcp", "target": "db-replica.internal:5432", "intervalSec": 60, "timeoutSec": 5, "consecutiveFails": 3, "alertMessage": "Реплика не принимает соединения.", "recoveryMessage": "Реплика снова доступна." }'
# TLS — alert 30 days before certificate expirycurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "appid": 12345, "name": "SSL prod", "kind": "tls", "target": "example.com:443", "intervalSec": 3600, "timeoutSec": 10, "expectedStatus": 30, "alertMessage": "Сертификат example.com истекает менее чем через 30 дней!" }'
# DNS — resolve check via the specified servercurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "appid": 12345, "name": "DNS prod-зоны", "kind": "dns", "target": "example.com@8.8.8.8:53", "intervalSec": 300, "timeoutSec": 5, "alertMessage": "DNS-зона example.com не резолвится через 8.8.8.8" }'Examples by type
Section titled “Examples by type”Typical kind + target combinations for common tasks:
{ "kind": "smtp", "target": "mx.example.com:25" } // SMTP-MX responds{ "kind": "imap", "target": "imap.example.com:143" } // IMAP is alive (plain){ "kind": "pop3", "target": "pop3.example.com:110" } // POP3 is alive{ "kind": "ssh", "target": "jump.example.com:22" } // SSH banner{ "kind": "redis", "target": "redis.example.com:6379"} // Redis responds to PING{ "kind": "postgres", "target": "pg.example.com:5432" } // PostgreSQL accepts connections{ "kind": "mysql", "target": "db.example.com:3306" } // MySQL sends handshake{ "kind": "tls", "target": "smtps.example.com:465", "expectedStatus": 14 } // SSL certificate is valid and won't expire within the next 14 daysVia MCP (for an AI assistant)
Section titled “Via MCP (for an AI assistant)”If you have a Notifly MCP server set up (see MCP), just ask:
Create a monitor for https://api.example.com/health, check every 30 seconds, alert after 3 consecutive failures with text “API is down”, recovery “API is working again”.
Available MCP tools: list_monitors, create_monitor, update_monitor,
delete_monitor, pause_monitor, resume_monitor.
REST endpoints
Section titled “REST endpoints”| Method | Path | Description |
|---|---|---|
GET | /monitor | List user’s monitors |
POST | /monitor | Create |
PUT | /monitor/:id | Update settings (cannot change appid) |
DELETE | /monitor/:id | Delete |
POST | /monitor/:id/pause | Pause (checks are not performed) |
POST | /monitor/:id/resume | Resume |
POST | /monitor/test | One-off check (dry-run) without creating a monitor — returns ok, durationMs, details, error |
GET | /monitor-history/:kind/:id | Check history: aggregated buckets (uptime %, average response time); params bucket (1m/1h/1d), from, to |
GET | /monitor-history/:kind/:id/log | Latest check log entries; param limit (default 50, max 200) |
All endpoints require a client token (Basic Auth with username/password also works).
An MCP token needs write access for mutating operations (POST/PUT/DELETE, and pause/resume);
for reading (GET lists, history) and for POST /monitor/test read is sufficient.
The POST /monitor/test endpoint accepts { "kind", "target", "timeoutSec", "expectedStatus" }
and performs a single check right away, saving nothing — useful to verify target
reachability before creating a monitor:
curl -X POST "$NOTIFLY_URL/monitor/test" \ -H "Content-Type: application/json" \ -H "X-Notifly-Key: <client-token>" \ -d '{ "kind": "tcp", "target": "db.example.com:5432", "timeoutSec": 5 }'# → {"ok":true,"durationMs":42,"details":"connected"}You can view history for any monitor type by substituting the kind (for example
http, tcp, dns) and the monitor id.
Other monitor types
Section titled “Other monitor types”The /monitor described above are “lightweight” protocol checks (HTTP GET, TCP handshake,
DNS, TLS expiry). For more complex scenarios Notifly offers specialized
monitors with their own settings, timeout limits and separate REST APIs:
- HTTP monitors — full HTTP requests with method, headers, body, status/content/time checks (timeout up to 30 s).
- Content monitors — watch for page content changes (hash, keyword, regex), timeout up to 60 s.
- Port monitors — check a host’s set of ports (timeout up to 10 s).
- Port scanning — detect opened/closed ports and notify on changes.
- Workflow monitors — chains of HTTP steps with value extraction and assertions (timeout up to 60 s).
- Browser-workflow — scenarios in a real browser (clicks, input, page checks), timeout up to 120 s.
Related monitoring features:
- Metrics — ingest numeric metrics and alert on thresholds.
- Domain verification — confirm ownership of a host.
- Heartbeat — the reverse scenario: the service periodically “pings” Notifly, and an alert is sent on missed pings.
Why YDB, not S3
Section titled “Why YDB, not S3”See the same argumentation for heartbeat: an indexed
point query by next_check_at is cheaper and faster than enumerating S3 objects.
Limitations
Section titled “Limitations”- Minimum period: 30 seconds (to avoid overloading YDB).
- Maximum period: 24 hours (for very rare checks it’s better to use heartbeat).
- A single
notifly-monitorinvocation processes up to 150 overdue monitors (the cron runs once per minute, checks run in parallel, by default up to 100 concurrently; if there are more overdue items the function self-invokes). - Requests originate from Yandex Cloud, so the target resource must be reachable from the public internet (or from a private YC network if the function is in the appropriate VPC).
- All protocol-specific checks (
smtp/imap/pop3/…) are performed without StartTLS — for an encrypted variant use the already-encrypted port (:465,:993,:995,:6380) withkind: "tls"orkind: "tcp".