Monitoring checks
Each domain can have any combination of three check kinds enabled. On
every heartbeat, Dominder runs all enabled checks for that domain in
parallel and aggregates the result into one ofok,warning, orfailing.
How results are aggregated
failing- any enabled check failed.warning- all checks passed but at least one emitted a warning (e.g. SSL within expiry window).ok- all checks passed without warnings.unknown- no check has run yet (freshly added domain).
Scheduling
Domains are checked on a rolling schedule. After each run, the next run
is set tonow + intervalMinutes. The default interval is configured server-side (typically 5 minutes)
and you can override it per-domain viaintervalMinutes(1-1440).
The scheduler wakes up every 30 seconds and claims any domains whose
scheduled time is in the past. A paused domain (paused: true) is skipped entirely.
Status check (HTTP reachability)
Enabled by:monitor.status = true
What we do
- Resolve the hostname.
- Send
GET https://with a 10 second timeout./ - If that fails (DNS error, connection refused, timeout, TLS error), fall
back to plain
http://.
When it's OK
- Any response with status code less than 400.
When it fails
- The server returns 4xx or 5xx.
- Connection refused, DNS failure, timeout, or TCP reset on both https and http.
Example result line in a check result / webhook payload
{ "kind": "status", "ok": true, "message": "HTTPS 200" }
{ "kind": "status", "ok": false, "message": "Unreachable (https: timeout; http: ECONNREFUSED)" }SSL check (TLS certificate health)
Enabled by:monitor.ssl = true
What we do
- TLS handshake on port 443 with strict verification and SNI set to the hostname.
- Inspect the presented certificate.
When it's OK
- Handshake succeeds, certificate chains to a trusted root, hostname matches, and expiry is more than 14 days out.
When it warns (but still OK=true)
- Certificate expires within 14 days.
When it fails
- Expired certificate.
- Self-signed or untrusted chain.
- Hostname mismatch.
- Handshake timeout or connection error.
Example result lines
{ "kind": "ssl", "ok": true, "message": "Valid - expires in 42 day(s)." }
{ "kind": "ssl", "ok": true, "warning": true, "message": "Certificate expires in 3 day(s) (Jun 12 23:59:59 2026 GMT)." }
{ "kind": "ssl", "ok": false, "message": "Certificate expired on 2026-04-21T23:59:59.000Z" }
DNS record verification
Enabled by:monitor.records = true and at least one entry in therecords array.
Record shape
{
"type": "A", // A | AAAA | CNAME | MX | TXT | NS
"host": "www", // subdomain prefix; "" means apex
"expected": "example.com" // what the record should resolve to
}
Thehost field
- Empty string (or omitted) means the apex - we look up the domain itself.
- Non-empty - we prepend it, so
host="www"onexample.comquerieswww.example.com. - May contain dots, e.g.
"mail.eu"to buildmail.eu.example.com.
Matching rules by record type
| Type | Lookup | Expected value format | Match rule |
|---|---|---|---|
A | IPv4 addresses | 93.184.216.34 | Case-insensitive equality; expected must be in the returned set. |
AAAA | IPv6 addresses | 2606:2800:220:1:248:1893:25c8:1946 | Case-insensitive equality; expected must be in the returned set. |
CNAME | CNAME target | example.com | Case-insensitive equality; trailing dot is ignored. |
MX | MX records | 10 mail.example.com or justmail.example.com | Match is true if either the exact "priority host" string or just the host matches any MX record. |
TXT | TXT records | v=spf1 include:_spf.google.com ~all | Exact string match (case-sensitive). |
NS | Name servers | ns1.example-dns.com | Case-insensitive equality; expected must be in the returned set. |
Example result lines
{ "kind": "record", "ok": true,
"message": "A example.com -> 93.184.216.34 matches (93.184.216.34)" }
{ "kind": "record", "ok": false,
"message": "CNAME www.example.com -> example.com MISMATCH - currently cdn.someoneelse.net" }
{ "kind": "record", "ok": false,
"message": "A mail.example.com -> 1.2.3.4 lookup failed: ENOTFOUND" }