# Alerts

> Rules you define in plain language, plus Fixter's own detectors that alert on error bursts and anomalies without configuration.

Alert rules in Fixter come from two places: the ones you define, and the ones Fixter's
detectors create on their own. Both are the same kind of rule, both live under
[Alerts](https://app.fixter.dev/alerts), and you can review, edit, or disable either.

## Three ways a rule gets created

### 1. From Claude Code

Run onboarding; its `alert-setup` stage turns what matters into rules:

```
/fixter:onboard
```

It resumes from where it stopped and runs alert setup. (Asking in plain language can also
work, but skills are triggered by the model rather than by a command, so `/fixter:onboard`
is the reliable way to run the stage.) It reads your project to work out which flows are
worth watching, proposes rules for them, and creates the ones you accept. Payment
failures, authentication errors, and latency on a checkout path are the shape of what
comes out.

Thresholds are calibrated against your data, so it checks how many logs you have first.
On a service that started reporting minutes ago it recommends deferring and suggests
returning after a day, offering safety-net rules in the meantime. That is expected rather
than a failure.

Any other MCP agent can do the same through the
[alerting MCP tools](/reference/mcp-tools/#alerting).

### 2. Fixter creates them for you

Fixter runs its own detectors over your data continuously and creates rules from what
they find: error bursts, statistical anomalies, and error budget burn. These alert you
immediately. You do not accept them first, and you need no rule of your own for them to
fire.

So a service is covered from the moment it starts reporting, including the stretch where
your own thresholds cannot be calibrated yet. Rules created this way are marked as such
and behave like any other rule, so you can retune or disable one that is not useful.

### 3. By hand in the app

Open [Alerts](https://app.fixter.dev/alerts) and create a rule. You can also start from
a query you are already looking at: **Alert on this** on the
[Logs page](https://app.fixter.dev/logs) carries the current query into a new rule.

Rather than starting blank, the editor offers templates that fill in a working rule you
then adjust:

| Template | What it watches |
| --- | --- |
| Something gets slow | p95 latency crossing a limit |
| Errors spike | error rate climbing |
| Error budget burns | SLO burn rate over two windows |
| A metric crosses a line | any OTel metric you send |
| Traffic drops | requests falling below the learned normal |
| From scratch | an empty rule |

## What you fill in

Whether you started from a template or from scratch, a rule is these parts:

- **Source.** Which signal to read: `logs`, `spans`, or `metrics`. This is the first
  choice because it decides which measures you can use.
- **Filter.** The slice you care about, written in [QuerySQL](/reference/querysql/) with
  field and value suggestions as you type, for example
  `service = 'checkout' and kind = 'SERVER'`.
- **Measure.** What to compute over that slice. The offer depends on the source:

  | Source | Measures |
  | --- | --- |
  | `logs` | `count`, `rate_per_min`, `avg`, `sum`, `min`, `max`, `p50`, `p95`, `p99` |
  | `spans` | `request_count`, `error_rate`, `p50`, `p95`, `p99` latency, `error_burn_rate`, `latency_burn_rate` |
  | `metrics` | `count`, `sum`, `avg`, `min`, `max`, `p50`, `p95`, `p99`, `rate`, `delta` |

  Error rate and the two burn rates are span-only, so a service that sends no traces
  cannot alert on either. The burn rates take an error budget (and a latency threshold,
  for `latency_burn_rate`). On `metrics` the list narrows again to what the metric kind
  supports: percentiles and count and sum for histograms, average and min and max for
  gauges, rate and delta for counters.
- **Group by.** Optional. Splits the measure into one series per value, so a rule can
  watch latency per endpoint instead of one number for the whole service. Anomaly
  conditions cannot be grouped.
- **Window.** How many minutes of data each evaluation looks at.
- **Condition.** Either of:
  - **Threshold.** A comparator and a value, with separate **warning** and **critical**
    tiers, each requiring the condition to hold for a number of **consecutive windows**
    before it fires. Consecutive windows are what stop one spike paging you.
  - **Anomaly.** Compares the measure against its own learned baseline. You set the
    direction (is a rise bad, or a fall) and the sensitivity, rather than a number. This
    is what "Traffic drops" uses, since no fixed request count means trouble.
- **Composition.** Checks combine with AND and OR groups, so "error rate is high AND
  traffic is nontrivial" is one rule rather than two alerts you correlate by hand.

**Preview before you save.** The editor runs the rule against real historical data and
charts what it would have done, so you can see whether it would have fired constantly or
never. It is the difference between a rule you trust and one you mute in a week.

Rules are evaluated once a minute.

<!-- fx-image: the alert rule editor with a threshold condition and warning/critical tiers -->

## Where alerts arrive

**Slack by default.** Channels are connected under
[Settings > Integrations](https://app.fixter.dev/settings/integrations): connect the
workspace, add a channel, invite the bot. See [Slack](/setup/slack/).

**Webhooks** are the other type, covering PagerDuty, Opsgenie, and anything else that
accepts a URL, with optional custom headers.

Per rule you choose whether recovery notifies as well, and you can set a repeat interval
so a long-running incident keeps reminding you instead of firing once and going quiet.

That same Slack channel is where [investigations](/using-fixter/investigations/) happen:
flip its auto-investigate toggle on and every alert it receives is investigated in the
thread. One channel, both jobs.

## Keeping the noise down

Both of these are yours to configure. Fixter does not silence anything on its own:

- **Suppressions** silence matching alerts temporarily, for a deploy window or a known
  flapping dependency, without touching the rules themselves. You set them, and they
  expire.
- **Ignore rules** permanently drop known-noise signals before they can alert. Use these
  for the log line you will never care about.

Both are managed in the app alongside your rules, or through the
[alerting MCP tools](/reference/mcp-tools/#alerting) (`suppress_signal`, `create_ignore_rule` and
their list and delete counterparts), so you can tell your agent to mute something while
you deploy.

## If alerts are not behaving

- **A rule never fires.** Check the window and the consecutive-window count. A
  condition that holds briefly but not across consecutive windows is not supposed to
  fire. Preview the rule against historical data before assuming it is broken.
- **Anomaly rules stay quiet on a new service.** They need enough baseline history
  before they can judge a deviation, so a service reporting for minutes has nothing to
  compare against yet.
- **Alerts arrive but investigations do not follow.** Auto-investigate is off for that
  channel, or the bot was never invited. Turn the toggle on and run `/invite @Fixter`.
  See [Slack](/setup/slack/).

Still stuck? Email [info@fixter.dev](mailto:info@fixter.dev) and one of our founders will help you fix your problem asap.

## Related

- [Investigations](/using-fixter/investigations/): what happens after an alert fires
- [Debugging](/using-fixter/debugging/): the queries rules are built from
- [Slack](/setup/slack/): connecting the workspace and inviting the bot