System Status
Live service health, 30 or 90 days of uptime history and written incident reports
Every figure on this page comes from rows a probe writes to PostgreSQL every five minutes on the server. The uptime percentage is divided by the number of checks that were expected (288 per service per day), not by the rows that happened to be written; a check that was never written counts as downtime.
All Systems Operational
Services
Website
Main website
now 20ms · p50 30ms · p95 70ms (90 days) · measured inside the server
API
Backend API services
now 19ms · p50 36ms · p95 74ms (90 days) · measured inside the server
Database
PostgreSQL database
now 37ms · p50 35ms · p95 79ms (90 days) · measured inside the server
Contact form and newsletter delivery — derived from API health
Uptime Summary
| Day | Status | Uptime | Successful / expected checks |
|---|---|---|---|
| 2026-08-19 | No data | No data | 0/0 |
| 2026-08-20 | No data | No data | 0/0 |
| 2026-08-21 | No data | No data | 0/0 |
| 2026-08-22 | No data | No data | 0/0 |
| 2026-08-23 | No data | No data | 0/0 |
| 2026-08-24 | No data | No data | 0/0 |
| 2026-08-25 | No data | No data | 0/0 |
| 2026-08-26 | No data | No data | 0/0 |
| 2026-08-27 | No data | No data | 0/0 |
| 2026-08-28 | No data | No data | 0/0 |
| 2026-08-29 | No data | No data | 0/0 |
| 2026-08-30 | No data | No data | 0/0 |
| 2026-08-31 | No data | No data | 0/0 |
| 2026-09-01 | No data | No data | 0/0 |
| 2026-09-02 | Operational | 100% | 180/180 |
| 2026-09-03 | Operational | 100% | 289/289 |
| 2026-09-04 | Operational | 100% | 289/289 |
| 2026-09-05 | Operational | 100% | 288/288 |
| 2026-09-06 | Operational | 100% | 289/289 |
| 2026-09-07 | Operational | 100% | 288/288 |
| 2026-09-08 | Operational | 100% | 288/288 |
| 2026-09-09 | Operational | 100% | 289/289 |
| 2026-09-10 | Operational | 100% | 288/288 |
| 2026-09-11 | Operational | 100% | 288/288 |
| 2026-09-12 | Operational | 100% | 288/288 |
| 2026-09-13 | Operational | 100% | 288/288 |
| 2026-09-14 | Operational | 100% | 288/288 |
| 2026-09-15 | Operational | 100% | 288/288 |
| 2026-09-16 | Operational | 100% | 291/291 |
| 2026-09-17 | Operational | 100% | 138/138 |
Monthly uptime (SLA)
- 2026-0916 days measured100.00%
Checks run server-side every 5 minutes; days without records are shown in grey.
How this is measured
A scheduled job on the server calls the application's health endpoint every 5 minutes. A fully covered day should contain 288 rows per service.
The probe runs inside the application: if the application is down it does not write a failed row, it writes no row at all. That is why the percentage is divided by the expected number of checks rather than by the rows on disk — otherwise an outage could never show up.
Rows are kept for 90 days. Days older than retention, and days before probing started, stay grey; they are not outages and they do not lower the percentage.
Detected measurement gaps
No gap longer than two consecutive checks was detected in the retained window.
Because the measurement is taken from inside the server it cannot see problems in the network or CDN layer; an independent witness from outside the server is planned.
Incident history
Written records: what happened, what the root cause was and what changed. Automatically detected measurement gaps are listed under "How this is measured".
- Outage· Duration: 4 d 1 h
Full outage — hosting provider blocked the server IP
- Impact
- The site and every service behind it returned Cloudflare 523. Nothing reached the machine: HTTP, SSH and ICMP were all dead, and even a rescue boot came up without networking.
- Root cause
- A €16.58 hosting invoice dated 2 July was missed. The provider locked the account for non-payment and blocked the primary IP address. The disk, the OS and the application were all healthy — the outage lived entirely in the network layer.
- Resolution
- The invoice was paid and an unblock request was filed through the provider's console. Access came back in stages: ports 80/443 first, SSH and ICMP roughly three hours later. While diagnosing, a temporary jump host inside the provider's own network was used via ProxyJump, which proved the machine itself was fine and the block sat at the border; that host was deleted afterwards.
- Lesson
- Monitoring that runs inside the server goes quiet together with the server: no health ping left the box during the outage, so nobody was alerted. Permanent fixes: automatic payment on file, a dedicated mail filter for critical infrastructure invoices, and independent monitoring from outside the server. The "How this is measured" section on this page exists for the same reason.
- Near miss· no visitor impact
Near miss — a restart fired mid-build and looped the service
- Impact
- No visitor impact: the reverse proxy logged zero 502s during the window. The application process briefly entered a restart loop and hit the systemd start limit.
- Root cause
- While the app was being moved to a non-root system user, the five-minute health check fired mid-build and restarted a half-written build output. The same class of bug caused the module-not-found crash loop earlier in July: the build rewrites the directory that is being served, underneath the running process.
- Resolution
- A build lock was added to both the health check and the deploy script — no script may restart the service while a build is running — and the failed state is reset before every restart. The lock was verified with a synthetic build.
- Lesson
- Nothing automated may restart the service while a build is in flight. That rule now lives in the scripts themselves; remove it and the deploy falls back into the same loop.
Background jobs
The last run of the maintenance and automation jobs that keep the site going. A job that has missed more than twice its cadence turns yellow; a job that failed turns red.
Scheduled content publishing
5 min cadence
Up to dateEnd-to-end smoke test
15 min cadence
Up to dateNewsletter A/B winner selection
30 min cadence
Up to dateNewsletter drip delivery
once an hour
Up to dateEnquiry response-time check
once an hour
Up to dateDaily digest report
once a day
Up to dateDatabase backup
once a day
Up to dateGDPR data cleanup
once a day
Up to date
Frequently asked questions
How is the status on this page measured?
A scheduled job on the server calls the application's own health endpoint every 5 minutes and writes one row per service — web, API, database and e-mail — into the status_check table in PostgreSQL. The page reads nothing but those rows: no value is entered by hand and no tile starts out green by default.
Is the e-mail service probed separately?
No. E-mail health is derived from API health: no dedicated mail endpoint is called and no real message is sent. That is what the "derived from API health" note on the card means, and it is why no latency figure is shown for e-mail.
How is the uptime percentage calculated?
A fully covered day should contain 288 measurements (one every 5 minutes). The percentage is "successful checks / expected checks" — not divided by the rows that happened to be written. The probe runs inside the application, so if the application is down no row is written at all; a formula that ignores missing rows could never show an outage.
What do the grey days in the chart mean?
A grey day has no measurements at all, so no percentage is printed. Rows are kept for 90 days, which means days older than retention — and days before probing started — stay grey. They are not outages and they do not lower the percentage.
Where can I see past outages?
In the "Incident history" section on this page, with root cause and the lesson taken from it. Automatically detected measurement gaps and the written incident notes are also published at /status/feed.xml (RSS) and /status/feed.json (JSON Feed).
The page says operational but I have a problem — what now?
Measurements are taken from inside the server, so a network, CDN or region-specific problem can still look green here. You can report it via /contact/ — the time it happened and the country you were in are the most useful details.
Do you have this visibility in production?
This page is not decoration: checks are written every five minutes, a check that was never written counts as downtime, and every outage is published together with its root cause. If you want the same visibility for your own application, let's start with a short conversation.
- recorded checks
- 17,428
- measured days
- 16
- missing checks
- 0