# Routing rules and the default route

> How rules decide what happens to an event, in what order, and what happens when none of them match.

Web page: https://infrainbox.app/docs/notifications/routing/

Open **Notifications → Routing** (dashboard screen `/rules`). It's one screen: a rail of your rules on the left, in the order they run, and whichever rule (or the coverage overview) you've selected on the right.

## Order matters

Rules run top to bottom. **The first rule that matches decides the event's route** — dropped, kept in the inbox only, or opened as an incident — and its notification policy. A rule can also be marked **continue**, which doesn't decide anything by itself: it only adds its destinations, then evaluation keeps going to the rules below it. A rule routed **drop** is always terminal; nothing below it runs for that event.

Drag rules in the rail to reorder them, toggle one off without deleting it, or remove it entirely.

## Building a rule

Each rule has up to seven parts, walked through in order in its editor:

**1. When an event looks like this** — the condition. Leave it empty and the rule matches everything that reaches it. Build one from these fields:

| Field | Operators | Matches against |
|---|---|---|
| `source`, `source.integration` | eq, ne, in, glob | Which source or integration sent it |
| `severity` | eq, ne, in, gte, lte | The event's severity, by rank for gte/lte |
| `action` | eq, ne | `trigger` or `resolve` |
| `type`, `resource`, `title`, `body` | eq, ne, in, contains, glob, exists | Free text or the event's own dotted type |
| `tags` | contains, in, exists | Tags on the event |
| `metadata.<path>` | eq, ne, in, contains, glob, exists, gte, lte | Anything in the event's own metadata |
| `time` | within | A day/time window, in the workspace's time zone |

Conditions can be grouped and nested with **all**/**any**.

**2. Do this with it** — one of:

| Route | Effect |
|---|---|
| Drop | The event is hidden from the inbox and never opens an incident. |
| Inbox | Stays visible, but opens no incident. If you attach destinations, this becomes an *informational* notice — a one-off message about the event, not an alert about an ongoing incident. |
| Incident | Opens or updates an incident. |

**3. Who is told** — pick destinations (including `@default`, meaning the built-in InfraInbox Push plus whatever the [default route](#the-default-route) attaches), each optionally **without sound** (still delivered, just silent where the channel supports it — passive delivery on the phone, or without a notification tone on Telegram). An incident route with no destinations at all is a **silent incident**: visible everywhere in the dashboard, nothing pushed anywhere. A **delay** holds the first notice back — useful for "don't tell me unless this is still open in five minutes" — and only fires if the incident is still open and unacknowledged when the delay elapses.

**4. Re-notify** — repeat the notice while the incident stays open and unacknowledged: from what severity, how often (1 minute to 720 hours), and how many times at most. Acknowledging, snoozing or resolving stops the repeats.

**5. Fallback** — notify one more destination, once, when nobody has acknowledged after a delay, or when every delivery in step 3 failed outright.

**6. Repeats and recovery** — a **cooldown** (10 minutes if you don't set one) limits how often a *repeat occurrence* of the same open incident re-notifies a destination, separately from re-notify above. **Send a notice when the incident resolves** toggles whether this route hears about it at all when things clear.

**7. Change the event on its way through** — optionally **set severity** (a preset never does this — only your own rules can) and **add tags**.

## The default route

**Notifications → Routing → Default route** (dashboard screen `/rules/default-route`) is the rule every event that no other rule caught falls through to. It's always last, always enabled, and it's the one place a rule is defined **per severity** rather than by condition:

| Severity | What you set |
|---|---|
| CRITICAL, ERROR, WARNING | Route (drop, inbox or incident) and a full policy, same as any other rule |
| INFO, DEBUG | Same, though these usually stay in the inbox |
| SUCCESS | Fixed: a success never opens anything on its own — it only resolves the incident it matches (by `dedupKey` or fingerprint), and whichever destinations were already alerted get a Resolved notice |

The built-in InfraInbox Push is always part of the default route's reach — a severity routed to an incident here reaches every member's paired phone, on top of anything else you attach.

Changes here are saved from the save bar at the foot of the pane, which says how many severities changed; a save confirms with **Saved** and **Undo**, and leaving with unsaved changes asks first.

## Routing profiles

A routing profile changes **who is told** for some sources, without a rule per source: "Quiet: Telegram only, no push" for the projects that don't matter at 3 a.m., say. Manage them at **Notifications → Routing → Routing profiles** (dashboard screen `/rules/profiles`), listed below the default route with who each one tells and how many sources use it.

- **It replaces one thing.** For the sources it lists, a profile replaces the default route's destinations. Everything else still follows the default route: which severities open an incident, delays and re-notify. A severity the default route keeps silent stays silent, and the default route's fallback step isn't used for these sources.
- **It runs last.** Your own rules and the integration's preset still decide first; the profile only stands in for the default route.
- **InfraInbox Push is a choice.** Leave it out and those sources never reach a phone; the editor warns "No push" when you do.
- **Nobody at all is allowed.** A profile with no destinations makes those incidents silent: they stay visible in the dashboard, and no one is notified.
- **One profile per source.** Adding a source that another profile has moves it.

Pick a source's profile on the source's own page: its Overview tab has a **Routing** row (Default route or a profile), with **Edit profile** and **New profile from this source**. A source on a profile shows a **Custom routing** badge by its name. Members see all of this; owners and admins change it.

## Seeing what actually happens

The **Routing** screen's right pane, with nothing selected, shows **coverage**: one plain event per severity, run through your rules live (nothing sent, nothing stored), as a grid of destinations × severities. A filled mark means notified, a hollow one means notified silently, a warning mark means blocked right now (by a silence or quiet hours, say), and a dash means nothing is sent. It also calls out destinations no rule reaches at all for the source you picked, and destinations your rules do name but that can't deliver yet (an unpaired phone, for instance).

For a specific event rather than the coverage grid, use [Test an event](https://infrainbox.app/docs/notifications/dry-run.md) — the same button is one click away from both screens.

## Next

- [Presets](https://infrainbox.app/docs/notifications/presets.md) — the rules an integration ships, which run under your own
- [Quiet hours](https://infrainbox.app/docs/notifications/quiet-hours.md) and [Silences](https://infrainbox.app/docs/notifications/silences.md) — hold a notice back without touching routing
- [Test an event](https://infrainbox.app/docs/notifications/dry-run.md) — run a real or sample event through everything above, live
