Monitoring & alerts
Single source of truth: Better Stack (free plan) handles both uptime checks and the daily-backup heartbeat. On the free plan, alerts are delivered by email + the Better Stack mobile app (push) — outbound Discord/Slack/webhook notification channels are paywalled, so monitoring alerts do not go to Discord. UptimeRobot was retired in favour of Better Stack on 2026-06-15 (account since deleted) — its monitors were fully duplicated by Better Stack before removal, so nothing was lost.
Uptime monitors
| Monitor | URL | Type |
|---|---|---|
| Marketing apex | https://usetaikan.com/ | status (2xx) |
| Web app | https://app.taikan.fit/he/sign-in | status (2xx) |
| API health | https://api.taikan.fit/health | keyword |
- Web app is pointed at
/he/sign-in(a real 200 page), not the bare/— the root is a307 → /he/ → 404redirect chain and is a poor health signal. - API health is a keyword monitor that alerts when
"status":"ok"is absent. The endpoint (apps/api/src/app/health.controller.ts) returns HTTP 200 even when degraded (DB/Redis state lives in the body), so a plain status check wouldn’t catch a DB/Redis outage — the keyword does.
Backup heartbeat (dead-man’s switch)
The daily Postgres → R2 backup (Railway service pg-s3-backups) pings a Better Stack heartbeat (taikan-db-backup, period 1 day + 1h grace) only on a confirmed successful dump + upload. If no successful backup pings within ~25h, Better Stack alerts. This catches both a failed backup and a silently-stopped cron. The backup itself and restore steps: restore-from-backup.md.
Known constraints (free tier)
- Outbound chat channels (Discord/Slack/webhooks) are paywalled on the free plan — free alerting is email + mobile-app push only. There’s no free way to route Better Stack alerts into Discord (would need a paid tier or a custom incidents poller).
- Better Stack free also has no incoming webhooks, so there’s no free bridge for Sentry errors into this hub — Sentry errors stay in Sentry (its own email/mobile alerts).
Responding
- Uptime monitor down → confirm the service is actually unreachable, then see incident-response.md. For an apex/DNS outage specifically, check the Cloudflare apex record.
- Backup heartbeat missed → the nightly backup failed or the cron stopped. Check the
pg-s3-backupsservice in Railway and whether a fresh object landed in the R2 bucket; then restore-from-backup.md.
Setup tasks still pending
- Install the Better Stack mobile app and confirm push alerts are enabled (the real-time channel, since Discord is paywalled on free).
- (Optional) If Discord alerts are wanted, move the backup heartbeat to healthchecks.io (free, Discord-capable) by repointing
HEALTHCHECK_URL— no migration, uptime stays on Better Stack.