---
title: "Alert when database errors spike (hourly)"
method: POST
path: "/cron/db-error-spike"
tags: ["Cron"]
---

# Alert when database errors spike (hourly)

`POST /cron/db-error-spike`

## Request

- Base URL: `https://api.apphandoff.com/api`
- URL: `https://api.apphandoff.com/api/cron/db-error-spike`
- Auth: none required

Counts Postgres ERROR/FATAL/PANIC log lines over the last hour through the Supabase Management API logs endpoint. When the count passes DB_ERROR_SPIKE_THRESHOLD_PER_HOUR (default 5,000) it raises one in-portal notification and one owner email, at most once per 6 hours. per_hour is the error count; current_count, previous_count and delta are always null. ok is false when the error count cannot be read (read_failed, never treated as 0), the readings call fails, or the dedup stamp fails. notification.queued only says the fire-and-forget hand-off did not throw. The 6-hour dedup stamp is written only after the owner email is sent: a failed email is reported, leaves marked null so the next hourly run retries, and never fails the call. Protected by CRON_SECRET via the x-cron-secret header. Scheduled hourly by the db-error-spike stage of the hourly-sweeps schedule in .slipstream.json.

## Response `200`

Check result

- object
  - `ok` boolean, required
  - `outcome` 'below_threshold' | 'deduped' | 'alert' | 'read_failed', required
  - `current_count` unknown
  - `previous_count` unknown
  - `delta` unknown
  - `per_hour` integer, nullable
  - `threshold_per_hour` number
  - `notification` object, nullable
    - `queued` boolean
    - `error` string
  - `email` object, nullable
    - `ok` boolean
    - `error` string
  - `marked` boolean, nullable

## Other responses

- `401`: Missing or invalid CRON_SECRET

---

[API](https://skmtc.dev/apphandoff/apis/apphandoff-api.md) · [All operations](https://skmtc.dev/apphandoff/apis/apphandoff-api/llms.txt) · [OpenAPI document](https://skmtc.dev/apphandoff/apis/apphandoff-api/revisions/9f138fe46d56?raw)
