Monitoring that speaks TypeScript.
UptimeStatus is itself a Stacks app. Wire health routes, heartbeat pings, and deploy hooks into monitoring that feels like part of your stack.
Everything a Stacks app needs watched.
Health endpoints, monitored
Expose a health route from your Stacks app and point a health monitor at it. Failing checks open incidents and page the right channel.
Learn moreKnow when jobs stop running
Queue workers and scheduled jobs fail silently. A heartbeat monitor alerts you when the ping stops arriving.
Learn moreCertificates handled
Expiry warnings land weeks ahead, long before a browser warning does. No more calendar reminders for certs.
Learn moreThe services your app depends on
TCP checks watch your database, Redis, and queue ports, so you hear about it before your error tracker fills up.
Learn moreAlerts where your team lives
Slack, Discord, PagerDuty, Opsgenie, ntfy, webhooks: route each monitor to the channel that should wake up.
Learn moreA status page on your domain
Give your users a branded status page with real uptime history, subscriber emails, and an incident feed.
Learn moreOne line in a job, silence becomes an alert.
A cron that quietly stops is worse than one that crashes loudly. Add a ping to the end of any scheduled job's handle() and UptimeStatus treats missing silence as the incident it is.
We run this pattern on ourselves: our own worker fleet reports to a heartbeat monitor, and only on the healthy path, so a stuck queue can never pretend everything is fine. See cron & heartbeat monitoring.
// app/Jobs/NightlyBackup.ts export default new Job({ name: 'NightlyBackup', queue: 'maintenance', async handle() { await runBackup() // last line: report success await fetch('https://uptime-status.org/api/ping/your-token') }, })
Your app defines healthy. We enforce it.
Keep the logic where it belongs: a route in your app that checks the database, the queue, and whatever else matters, and returns JSON. A health monitor calls it on a schedule, records history, and pages someone when a check flips.
Alerting, retries, incident timelines, and the status page all come from outside your app, so a bug that takes your app down cannot take your alerting down with it.
// routes/api.ts route.get('/health', () => ({ db: db.isConnected(), queue: queue.isRunning(), storage: storage.isWritable(), }))
Dogfooded, in the honest sense.
This product monitors itself with its own heartbeats, runs its checks through its own queue, and serves this page from the same codebase you can clone. If the patterns here look natural in your Stacks app, that is because they were extracted from one.
Stacks questions, answered.
How do I monitor a Stacks scheduled job?
Create a heartbeat monitor, then hit its ping URL as the last line of your job's handle(). If the ping stops arriving within the grace period, an incident opens and your channels are notified. The pattern works for queue workers, nightly backups, and anything else on a schedule.
Does this replace @stacksjs/health?
They complement each other. Your app defines what "healthy" means in a route; a health monitor calls that route from outside on a schedule, keeps the history, and owns the alerting. Logic stays in your app, operations live here.
Is there an API for automation?
Yes. Monitors, status pages, and incidents are all plain JSON endpoints, so you can create monitors from a deploy hook or a buddy command. Everything the dashboard does goes through the same API.
Can I self-host it next to my app?
Yes. UptimeStatus is itself a Stacks app: clone it, run bun install and ./buddy serve, and you have the whole product on your own infrastructure, MIT licensed. One caveat: an external region watching your stack is worth keeping, because a monitor inside a failing network cannot report the failure.
Start monitoring in under 2 minutes.
No credit card required for the self-hosted, open-source version.