# 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://spaceflare.org/docs/servers/alerts · Updated 2026-08-22

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, the Game Protection kinds) 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 to 1000) is under the threshold | Score, 0 to 1000 (required) | Sustained |
| **Job fails** | A fleet job (install, benchmark, command…) reports failed | n/a | Once per job |
| **Cloudflare connection breaks** | A connected Cloudflare account's OAuth session is broken and needs reconnecting | n/a | Sustained, account-wide |
| **Tunnel goes down** | An L4 tunnel attached to a server reports down or failed | n/a | Sustained |
| **Benchmark finishes** | A benchmark run completes or fails | n/a | Once per run |
| **Attack starts** | OpenShield-XDP mitigation engages on the server | n/a | Sustained |
| **Attack ends** | OpenShield-XDP mitigation disengages | n/a | Once per attack |
| **Game node goes down** | The edge node serving one of your Game Protection services is unresponsive, failed, or disabled | Minutes (default 3, max 10080) | Sustained, account-wide |
| **Game config drifts** | A Game Protection edge node has not applied the service's latest config version | n/a | Sustained, account-wide |
| **Game WireGuard peer drops** | An active Game Protection service has a WireGuard peer that is not established | n/a | Sustained, account-wide |

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, the Game Protection kinds) 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)
