# Alerts: latency, errors, function failures and connections
Source: https://sovaria.in/docs/slo-alerts

Get an email or a signed webhook when your API gets slow, server errors climb, functions fail or your database runs out of connections — checked every minute, with a plan-based number of rules.

An alert rule watches one number over a window — say, the p95 latency of `GET /rest/v1/orders` over 15 minutes — and fires when it goes over your threshold. The project team gets an email (and an entry in the console's notification feed); a webhook gets a signed POST. When the number is back under the threshold for two checks in a row, the alert resolves and you hear about that too. Manage rules in **Observability → Alerts**.

## What you can alert on

| Metric | Unit | Scope | Measured from |
|---|---|---|---|
| `latency_p95_ms`, `latency_p99_ms` | ms | The whole project or one route | Gateway request latency (the same data as [Routes](https://sovaria.in/docs/logs-and-log-drains#routes)) |
| `error_rate` | % of requests answered 5xx | The whole project or one route | Gateway responses |
| `function_failures` | Failed runs in the window | Every function or one | Function runs that end failed, timed out or dead-lettered |
| `db_connections` | Connections | The project's database | The most connections the database held in the window (sampled every minute) |

- Windows: 5, 10, 15, 30 or 60 minutes. Route alerts — and every request alert on plans with 15-minute metrics (Free) — need 15 minutes or more.
- Request alerts ignore windows with fewer than `min_requests` requests (default 20), so one slow request at 3 a.m. doesn't page anyone.
- With no traffic at all, a firing alert stays firing (an outage that stops all requests must not look resolved) and an OK one shows **No data**.
- Route alerts cover every environment, or the ones you name (`env`, comma-separated ids; `main` = requests that named none).

## Create an alert

CLI:
```bash
sov alerts create --metric latency_p95_ms --threshold 800 --target "GET /rest/v1/orders" --window 15
sov alerts create --metric error_rate --threshold 2 --window 10 --webhook https://hooks.example.com/sovaria
sov alerts list
sov alerts test <rule-id>
```

JavaScript:
```ts
const rule = await sov.api.observability.alertsCreate({
  metric: 'error_rate', threshold: 2, window_minutes: 10,
  email: true, webhook_url: 'https://hooks.example.com/sovaria',
})
rule.signing_secret // whsec_… — shown once
```

Python:
```python
rule = await sovaria.api.observability.alerts_create(
    metric="function_failures", threshold=5, window_minutes=15, target="send-email")
```

Sovariq:
```text
Email me when the p95 of my orders API goes over 800 ms for 15 minutes.
```

Creating, changing and deleting rules needs a project owner or admin (or the service key); anyone on the team can read them. **Test** measures the rule now, says whether it would fire, and sends an `alert.test` to its webhook (no email).

## Webhooks

Webhook URLs must be public HTTPS hosts. Each delivery is a POST of JSON with `X-Sovaria-Event` (`alert.firing`, `alert.resolved` or `alert.test`) and `X-Sovaria-Signature: sha256=<hex>`, an HMAC-SHA256 of the raw body with the rule's signing secret (shown once, when you add the webhook). Answer with any 2xx.

Body:
```json
{
  "type": "alert.firing",
  "project_id": "f0c3e9a2-1b4d-4e7f-8a6c-2d9b5e3f1a07",
  "alert": { "id": "alr_3f9a1c0b7e2d4a6f", "name": "Slow orders", "metric": "latency_p95_ms", "threshold": 800,
             "unit": "ms", "window_minutes": 15, "target": "GET /rest/v1/orders", "env": null },
  "value": 2500,
  "since": 1792396800.0,
  "sent_at": 1792396801.4,
  "console_path": "/project/f0c3e9a2-…/observability/alerts"
}
```

Verify (Node):
```ts
import crypto from 'node:crypto'

export function verify(rawBody: Buffer, header: string | undefined, secret: string): boolean {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
  return !!header && header.length === expected.length && crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected))
}
```

## Plans

|  | Free | Pro | Ultra | Team | Enterprise |
|---|---|---|---|---|---|
| Alert rules per project (latency, errors, function failures, connections) | — | 10 | 25 | 50 | 200 |

When a project has more rules than its plan allows (after a downgrade), the oldest ones keep running and the rest wait, marked **Over plan limit**; nothing is deleted. Sovaria support can pause a rule that misbehaves (for example a webhook that keeps failing); only support can resume it.
