Status system

Disband's status page is self-hosted. It does not depend on a third-party status service, so it can still report accurately when the main web host, API, or static asset delivery is having trouble.

What the public page shows

The page groups monitors by service. For each monitor it shows:

Below the monitors are incidents, scheduled maintenance, and announcements. Each opens a detail page with the full update timeline. The feed publishes the latest 25 incidents, maintenance windows, and published announcements as RSS 2.0.

Checks

A Supabase Edge Function called status-probe runs every minute under pg_cron. It probes every enabled monitor in parallel and records one row per check.

Each monitor has:

Setting Meaning
Name The public label, for example Website.
Group The section it appears under, for example Disband.
URL The absolute http or https URL to request.
Method GET or HEAD. Defaults to GET.
Expected status The exact HTTP status that counts as healthy. Defaults to 200.
Keyword Optional text that must appear in the response body.
Timeout 1–30 seconds. Defaults to 10 seconds.
Headers Optional request headers, stored server-side.
Enabled Whether the probe requests it at all.
Public Whether it contributes to the public snapshot.

A monitor is healthy only when the status code matches and the optional keyword is present. Redirects are followed. A timeout, network error, wrong status, or missing keyword is recorded as a failed check with the reason.

The probe runs independently of the web app. A failure at the web host does not stop checks being recorded.

History and uptime

Every check is stored in status_checks. A database trigger folds each check into status_daily, so the 90-day bar is a cheap read rather than an aggregation over millions of rows.

A gap — a day with no checks — is shown as no data, not as downtime.

Automatic incidents

The probe opens an incident automatically when a monitor has failed three checks in a row. The incident is a major incident, linked to that monitor, and starts in Investigating with an automated update containing the last error.

When the next check succeeds, the incident moves to Resolved and an update records roughly how long the outage lasted. The incident stays on the page and in the feed with its full history.

If a service is flapping but not failing three times consecutively, no automatic incident is opened. The owner can still add a manual update to an automatic incident while it is open.

Manual incidents, maintenance, and announcements

The owner can publish three kinds of entry:

Kind Use for
incident An unplanned problem.
maintenance Planned work, optionally with a start and end time.
announcement A general service notice that is not an outage.

An incident can affect none, one, or several monitors. Its impact is one of none, minor, major, or critical.

The update statuses are:

Every update adds a timestamped entry to the incident timeline and sets the incident's current status. Marking an update resolved or completed also sets the resolved time. Posting a later update with another status reopens it.

Overall status

The banner is decided in this order:

  1. An active maintenance window says Maintenance in progress, or Scheduled maintenance before it starts.
  2. An active major or critical incident says Major outage.
  3. An active minor incident says Partially degraded.
  4. Failed monitors say Partially degraded, or Major outage when every public monitor is failing.
  5. With no failures and at least one result, it says All systems operational.
  6. Before the first checks land, it says Waiting for the first checks.

Resolved incidents do not affect the banner.

Privacy

The public read path is a database function, not direct table access. It returns monitor names, groups, states, latency, uptime, and incidents. It deliberately omits:

The base tables have row-level security enabled with no public policies. Only the service role and the probe function can read them directly.

Administration

/status/admin is restricted to the signed-in platform owner. It is not a space role and cannot be granted to another member. Unauthenticated requests receive 401; other signed-in accounts receive 403.

The admin screen can:

Admin API

The screen uses these owner-only routes:

Method Endpoint
GET, POST /api/status-admin/monitors
PATCH, DELETE /api/status-admin/monitors/{id}
GET, POST /api/status-admin/incidents
PATCH, DELETE /api/status-admin/incidents/{id}
POST /api/status-admin/incidents/{id}/updates

They accept the owner's Supabase access token as Authorization: Bearer <token>. They are implementation details of the admin screen, not a public API; the shape can change.

Operational notes