# Alerts

> Alert rules watch your servers, tunnels and Cloudflare connections and notify you in-app, by email or via webhook the moment a condition trips.
>
> Canonical: https://xdp.network/docs/servers/alerts · Updated 2026-08-17

The alerts engine watches your fleet around the clock. You define rules under
**Settings → Alerts**; a 60-second sweep evaluates every enabled rule and notifies
the channels you picked the moment a condition trips — and again when it clears.

## Create a rule

Go to **Settings → Alerts** and choose **New rule**. Each rule has:

- **When** — the condition to watch (the rule kinds below).
- **For** — the target: all servers, or one specific server. Account-wide conditions
  (Cloudflare connection breaks) have no server picker.
- **Threshold** — only on the kinds that take one: minutes offline, or a score floor.
- **Notify via** — one or more channels: in-app (the notification bell), email,
  webhook. A rule must keep at least one channel.
- **Enabled** — paused rules never fire.

Rules can be edited in place afterwards — threshold, channels, enabled — or deleted,
which also removes their event history.

## Rule kinds

| Rule | Fires when | Threshold | Behavior |
| --- | --- | --- | --- |
| **Server goes offline** | No heartbeat for longer than the threshold | Minutes (default 3, max 10080) | Sustained |
| **Score drops below** | The health score (0–1000) is under the threshold | Score, 0–1000 (required) | Sustained |
| **Job fails** | A fleet job (install, benchmark, command…) reports failed | — | Once per job |
| **Cloudflare connection breaks** | A connected Cloudflare account's OAuth session is broken and needs reconnecting | — | Sustained, account-wide |
| **Tunnel goes down** | An L4 tunnel (BYOS or Tunnel With Us) reports down or failed | — | Sustained |
| **Benchmark finishes** | A benchmark run completes or fails | — | Once per run |
| **Attack starts** | OpenShield-XDP mitigation engages on the server | — | Sustained |
| **Attack ends** | OpenShield-XDP mitigation disengages | — | Once per attack |

Attack kinds come from the daemon's heartbeat: when OpenShield-XDP is installed, the
daemon probes its local state and the platform derives the start/end transitions.
A `score_below` rule skips servers that are offline — `server_offline` owns that
alert, so one outage never fires two rules.

## How firing and resolving work

**Sustained** conditions (offline, low score, broken connection, tunnel down, attack
started) fire a single event on the transition edge — not on every sweep. The event
stays **Open** while the condition holds, and resolves with a "Resolved:"
notification when it clears. If a sweep can't tell (for example, stale data), the
open event is left alone rather than flapping.

**Point-in-time** kinds (job fails, benchmark finishes, attack ends) fire once per
occurrence and are recorded already resolved — each occurrence is deduplicated, so
you never get the same event twice.

Every fired and resolved event lands in the **Recent events** card on the same page,
with an **Open only** filter for what's active right now.

## Channels and delivery

- **In-app** — a row in the notification bell.
- **Email** — sent to your account address.
- **Webhook** — an HTTP POST to the one delivery URL per account, configured in the
  **Delivery** card at Settings → Alerts. Payloads auto-format for Slack
  (`hooks.slack.com`) and Discord (`discord.com/api/webhooks`); any other HTTPS
  endpoint gets the raw JSON envelope (kind, phase, title, body, URL, server,
  payload). Delivery is best-effort. The **Send test** button fires a sample payload
  at the *saved* URL — save first if you just changed it. Leave the URL empty to
  disable webhook delivery; rules with the webhook channel but no URL saved show a
  warning on the rule row.

## The digest email

The Delivery card also carries a **Daily digest email** toggle. With it on, you get a
fleet digest — servers online, average health score, alerts fired by kind, completed
benchmarks and attack start/end counts — every day, plus a 7-day roll-up on Mondays.
Digest mail additionally requires the **Digest** row in the notification matrix
(below) to have email enabled; it defaults off, so digests are strictly opt-in.

## Notification preferences

**Settings → Notifications** holds the per-event matrix: rows for every notification
type, columns for in-app and email. Each alert rule kind has its own row in the
**Alerts** group, so you can silence (for example) benchmark-finished emails while
keeping the in-app bell. The matrix gates the in-app and email channels of every
rule — the webhook channel is per-rule only and always posts when picked.

## Next steps

- [Health Monitor](/docs/servers/health-monitor) — enroll servers and read the health score
- [Troubleshooting](/docs/troubleshooting/common-issues)
- [REST API](/docs/reference/api)
