The status page that stays up when your database doesn’t.

Statuskeel serves your page from its own service, which answers from a snapshot kept in memory and Redis. If Postgres or the console behind it goes down, visitors still get the page, marked with how old it is, instead of an error.

Sign in with GlobalArtID. Your page lives at you.statuskeel.com or on your own domain.

check · hooks.acme.ioevery 60 s
GET https://hooks.acme.io/health
expect 200 · slow after 800 ms · 3 in a row

14:02:10  200  1 912 ms  slow 1/3
14:03:10  200  2 204 ms  slow 2/3
14:04:10  200  2 087 ms  slow 3/3

✓ two checkers agree
→ Webhooks: degraded performance
→ incident opened

$ 
Checks: HTTP(S), every 30 s to 1 h, by plan
Acme status / Incidents1 open
Webhooks are slow to respondInvestigatingMinorAffects Webhooks
Investigating 14:09
Deliveries are slower than usual. We are looking at the queue workers.
Opened by the check 14:04
Two checkers saw answers slower than 800 ms, three times in a row.
Subscribers notifiedemail 212 · slack 3 · webhook 5
Statuskeel: incidents, updates, subscribers
acme.statuskeel.comserved from snapshot
Acme statusSubscribe to updates
Degraded performance
APIOperational
WebhooksDegraded performance
90 days ago99.95%Today
Your page: served from a snapshot

Two paths, and visitors only take the short one

Everything you change goes in through the write path. Each change rebuilds the page’s snapshot and stores it in Redis with no expiry; it is rebuilt every two minutes as well.

Visitors are answered by public-web, a separate service with its own replicas. It reads memory first, then Redis, and asks the services behind it only when both come up empty.

Write pathyou, your tools, the checks
consoleREST APIAlertmanagerchecks
servicespages, incidents, metrics
Postgresthe record
snapshoton change, every 120 s
Redisno expiry
Read pathyour visitors
visitorpage, JSON, feeds
public-web2 replicas or more
memoryfresh for 10 s
Redisthe same snapshot
servicesonly if both miss
acme.statuskeel.comPostgres down
Live updates are unavailable right now, so this page shows the last state it managed to read — collected 4 minutes ago.
All systems operational
APIOperational
DashboardOperational
GET /api/v2/status.json
"snapshot": {
  "stale": true, "age_seconds": 241, "source": "cache"
}
Keeps answering
The page, its JSON and its feeds are built from the same snapshot, so they stay up together.
Says it is stale
Visitors see how old the page is, and the JSON carries stale, age_seconds and source for anyone polling it.
Keeps HTTPS
Certificates for your own domain are issued over HTTP-01 and served by public-web itself, from memory and Redis.
Needs no billing
Rendering a page never calls billing; your plan’s history depth is written into the snapshot.
Does not survive
Losing the whole cluster, or losing Redis while a public-web pod restarts and forgets its memory.

The page your customers read

Server-rendered HTML, answered by the service that keeps the snapshot. It carries your logo, favicon and accent; the status colours are the same on every page, so an outage looks like an outage everywhere.

  1. Your brand, checked

    Your logo and accent on the header and the button. An accent too pale to read is kept off text, and links fall back to ink.

  2. One line on top

    The worst status on the page, in words, with the colour behind it rather than instead of it.

  3. Updates, newest first

    The impact carries the colour; the lifecycle stays grey until the incident is resolved.

  4. One bar per day

    Hover a day, or tab to one that had an incident, to see what happened and for how long.

What it does

The parts of Statuskeel, grouped by who touches them: your visitors, your team, and the automation that works while nobody is looking.

Pages and components

What your visitors read.

Address
acme.statuskeel.com, or a subdomain of yours such as status.acme.io with one CNAME record. The certificate is issued for you; we never ask for access to your DNS.
Components
Grouped, described and shown in the order you choose.
Statuses
  • Operational
  • Under maintenance
  • Degraded performance
  • Partial outage
  • Major outage
  • Unknown
Uptime
A bar for each day, up to 90 days depending on your plan. A major outage counts in full, a partial outage half, degraded performance a quarter, and maintenance windows are left out.
History
Correct the history by hand. The edit is marked as manual, kept in the activity log, and the uptime is counted again.

Incidents and maintenance

What your team writes.

Lifecycle
  • Investigating
  • Identified
  • Monitoring
  • Resolved
Impact
  • No impact
  • Minor
  • Major
  • Critical

Set per component. The components follow it for as long as the incident is open.

Templates
Save the incidents you write again and again, and start the next one from a template.
Postmortems
Add a postmortem to an incident, and it appears on the incident’s public page.
Maintenance
Scheduled windows start and finish themselves, and subscribers are warned before they begin.
Console
In English, Russian and Serbian, with an activity log of who changed what.

Automation

What runs while nobody is looking.

HTTP checks
HTTP and HTTPS: the expected code, a latency limit, a timeout, and an interval from 30 seconds to an hour, depending on your plan.
Agreement
A status changes only when at least two independent checkers agree: after three bad answers in a row by default, and back after two good ones.
Silence
When the checks stop reporting, the page says so and shows Unknown rather than green.
Incidents
A failing check opens its own incident, closes it on recovery, and reopens it if the outage returns within 30 minutes.
People first
An incident your team opened holds the component for as long as it is open, and a status set by hand holds it for an hour; the checks wait.
Metrics
Charts from Prometheus, Datadog, or numbers you push through the API, shown next to the components.

Telling people

Who hears about it, and how.

Channels
Email with double opt-in, Slack, and webhooks signed with HMAC-SHA256.
Scope
Subscribe to the whole page, or only to the components you depend on.
Feeds
RSS and Atom feeds of incidents, for readers and tools that poll.
Delivery
Five attempts with a growing pause between them, and one message per update, never two.

Works with the tools you already run

Set statuses from a script, from Alertmanager or from the console, and read them back as JSON. The API and incoming webhooks live at https://api.statuskeel.com.

REST v1 · set a component’s statusapi.statuskeel.com
$ curl -X PATCH \
    https://api.statuskeel.com/v1/pages/$PAGE/components/$API \
    -H "Authorization: OAuth skeel_4f9c…" \
    -H "Content-Type: application/json" \
    -d '{"component":{"status":"degraded_performance"}}'

{
  "id": "1f0c…",
  "name": "API",
  "status": "degraded_performance",
  "showcase": true
}

Organization keys with read or write scope, sent as Authorization: OAuth skeel_4f9c…. The same API lists and posts incidents, schedules maintenance, adds subscribers and takes metric data.

Public JSONno key needed
$ STATUS=https://acme.statuskeel.com
$ curl $STATUS/api/v2/summary.json
{
  "status": {
    "indicator": "major",
    "description": "Partial System Outage"
  },
  "components": [ 7 ], "incidents": [ 1 ],
  "snapshot": {
    "stale": false, "source": "memory"
  }
}

Paths and field names are modeled on Atlassian Statuspage’s public API. The JSON is built from the same snapshot as the page, so it keeps answering with it.

alertmanager.ymlPOST /webhooks/alertmanager
receivers:
  - name: statuskeel
    webhook_configs:
      - url: https://api.statuskeel.com/webhooks/alertmanager?page=$PAGE
        http_config:
          authorization: { type: OAuth, credentials: skeel_4f9c… }
        send_resolved: true

# labels on the alerting rule
component: $API
statuskeel_status: degraded_performance

A firing alert sets the component whose ID is in its component label, and a resolved one sets it back to operational. A statuskeel_status label picks the status; statusdeck_status is still read.

webhook deliveryHMAC-SHA256
POST /hooks/statuskeel
X-Statuskeel-Event: status_update
X-Statuskeel-Delivery: 5b7d…
X-Statuskeel-Signature: sha256=9f2b…

{
  "event": "status_update",
  "subject": "Acme — Elevated API errors",
  "status": "investigating",
  "page": { "name": "Acme", … },
  …
}

What your webhook subscribers receive: each delivery is signed with HMAC-SHA256. Until the old names retire, X-Statuskeel-* and X-Statusdeck-* headers are both sent with the same values.

<img src="https://acme.statuskeel.com/embed/badge.svg" alt="Acme status">
renders as statusPartial outage

An SVG badge for your README, and RSS and Atom feeds of incidents at /history.rss and /history.atom.

Pricing

Plans and prices come straight from billing, so they are the ones you will see in the console.

Prices in USD. Limits apply to the whole organization, across all of its pages.

Free
$0

Start in the console
Pro
$12/ month

Paid through PayPal

Start in the console
PagesFree1
ComponentsFree10
SubscribersFree100
Custom domainsFree—
Shortest check intervalFree5 min
History on the pageFree30 days

Start with one page and one record.

Create the page in the console, add your components, and point a subdomain of yours at it when you are ready.

DNS · acme.ioone line
; at your DNS provider
status.acme.io.  CNAME  acme.statuskeel.com.

✓ record verified
✓ certificate issued, renews itself
$