status page

Building a status page: in-house vs. hosted

Every modern service has a status page. They look simple — green dots, a few recent incidents — but the decisions behind them shape how your team communicates during outages. Here's the honest comparison of in-house vs. hosted, with code examples for the build-your-own path.

MyUptimeBot Team · June 9, 2026 · 6 min read · For developers

What a status page is for

A status page exists to answer one question fast: “is the service working right now?”

Secondary questions:

  • “Is this a known issue?”
  • “When did it start?”
  • “What’s the ETA on a fix?”
  • “Has this happened before?”

A good status page answers the first question in 1 second and the rest within 10 seconds of clicking around. Everything else is decoration.

The bar is lower than people think. Even a static HTML page that says “All systems operational” updated by hand is dramatically better than no status page at all, because it gives customers somewhere to look that isn’t your support inbox.

In-house vs. hosted: the honest tradeoffs

Hosted status pages (Statuspage by Atlassian, BetterStack, Statuspal, Hund, Instatus) handle the entire surface for you. You get a dashboard, automated incident messaging, subscriber notifications via email/SMS/Slack, a clean URL like status.yourcompany.com, and historical uptime tracking.

  • Cost: $30–$500/month depending on tier and subscriber count
  • Time to set up: 30 minutes
  • Maintenance: near zero

Self-hosted status pages can be:

  • A static page (HTML, generated nightly from monitoring data)

  • A small app you build (Express, Rails, Next.js — pull data from your monitoring API)

  • An open-source tool (Cachet, Statping, Uptime Kuma’s status page mode, Vrok)

  • Cost: Hosting only (often $0–$20/month)

  • Time to set up: 2–20 hours depending on approach

  • Maintenance: ongoing

The right choice depends mostly on whether you have subscribers — people who want to be notified when an incident is declared.

The subscriber notification problem

If your customers don’t want to get notified when there’s an outage, a static page is fine. You update it during incidents (or generate it from monitoring data), and customers check it when they suspect something’s broken.

If your customers do want notifications — and most B2B SaaS customers expect this — you need infrastructure: email delivery at scale, SMS routing, possibly Slack/webhook integrations, subscriber management (opt-in/opt-out, GDPR, double-confirm), and reliability so notifications go out during an outage (which is exactly when your own infrastructure might be unreliable).

Hosted services solve this for you. Self-hosted means you’re building or integrating it. For most teams, the math says hosted is worth it the moment you have more than a handful of subscribers.

When self-hosted makes sense

The case for building it yourself:

  1. No subscriber notifications needed. Pure status display, occasionally updated.
  2. You want a specific design that hosted services don’t allow.
  3. You want it tightly integrated with your existing systems — incident channels, deploy pipelines, custom event types.
  4. You’re cost-sensitive and have engineering time to spend.
  5. You’re already running good monitoring and just need to surface it publicly.

A static-generation approach works well for most of these. You run a script every minute that queries your monitoring system, computes “are all systems green?”, and rewrites a small HTML file. Stick it on a CDN. Done.

A minimal in-house status page

Here’s the bones of a Node.js service that pulls from a monitoring system and serves a status page:

const express = require('express');
const app = express();

app.get('/status', async (req, res) => {
  const monitors = await fetchMonitors();
  const overallStatus = monitors.every(m => m.status === 'up')
    ? 'operational'
    : 'degraded';

  res.render('status', {
    overallStatus,
    monitors,
    lastUpdated: new Date()
  });
});

async function fetchMonitors() {
  // Call your monitoring service's API
  return [
    { name: 'Web app',     status: 'up',   uptime30d: 99.98 },
    { name: 'API',         status: 'up',   uptime30d: 99.95 },
    { name: 'Background',  status: 'up',   uptime30d: 99.99 }
  ];
}

That’s the basic version. To make it useful you add:

  • Cache the API response for 30–60 seconds so the page doesn’t hammer your monitoring API
  • Add incident management — a table that lets you manually post current incidents
  • Add historical uptime charts — daily uptime % over the past 90 days
  • Add an RSS or JSON feed so external tools can subscribe

The whole thing is a few hundred lines of code. The hard part isn’t the page — it’s the discipline of keeping it updated during incidents.

The “host it elsewhere” rule

The most important thing about a status page: don’t host it on the same infrastructure as the thing you’re monitoring.

If your status page is on the same cloud provider, behind the same DNS, going through the same CDN as your main app — then when the main app goes down, the status page usually goes down with it. Customers can’t find out what’s broken because the status page is broken too.

Hosted status page services solve this by being on entirely separate infrastructure. If you self-host, the rule is to put the status page somewhere else — a different cloud, a static CDN, or even just a $5 VPS with no other purpose. Cost is negligible; the independence is invaluable.

Open-source self-hosted options

If you want a richer setup than rolling your own from scratch, but want to keep it self-hosted, the open-source landscape has options:

  • Statping-ng — Go-based, easy to deploy, includes notifications and an admin UI
  • Cachet — PHP/Laravel, mature, more configuration overhead
  • Uptime Kuma — primarily a monitor, but its status pages mode is decent
  • Vrok — newer, Rust-based, lightweight

All of these need ongoing maintenance — security patches, dependency updates, monitoring of the status page itself. Free in dollars, not free in time.

What to put on the page

The bare minimum for a useful status page:

  1. Overall status indicator — a big colored badge: “All systems operational,” “Some systems degraded,” “Major outage”
  2. Component breakdown — each major service or feature, with its current status
  3. Current incidents — anything ongoing, with first-posted time and last update
  4. Recent incidents — last 5–10 incidents, even if resolved
  5. Historical uptime — a 90-day calendar grid or simple percentage

Optional but useful:

  • Scheduled maintenance — upcoming windows where you’ll be intentionally down
  • Subscribe to updates — email, RSS, Slack webhook, SMS
  • Per-region status — useful if you have customers in different geographies
  • Performance graphs — response time over time

Things that make status pages worse:

  • Too much detail. Customers don’t need to know about every microservice. Group things into customer-facing categories.
  • Stale information. A page that hasn’t updated in 6 hours is worse than no page — it signals you’ve forgotten about the outage.
  • Self-congratulatory uptime stats. “99.999% uptime over 90 days!” looks dishonest when there’s a current outage. Just show the data.

Automating incident posts

The single biggest improvement most teams can make is automating incident posts from monitoring alerts.

The flow:

  1. Monitoring detects an outage and creates an alert
  2. A webhook fires that auto-creates an incident on the status page
  3. Customers subscribed to status updates get notified
  4. When monitoring sees the outage clear, a corresponding webhook fires to mark the incident resolved

Most hosted status page services have native integrations for this. Self-hosted requires you to wire it up — usually a small webhook handler that translates monitoring events into status page incidents.

The benefit is the status page stays updated even when the human running it is busy fixing the outage. Customers see “we detected an issue at 14:42” within seconds of the actual problem starting.

My honest recommendation

For most teams:

  • Sub-100 customers, no subscriber notifications needed: Static page or open-source self-hosted. Update manually. Spend the saved money on better monitoring.
  • 100+ customers expecting notifications: Use a hosted service. The maintenance burden of building this in-house outweighs the cost.
  • Enterprise with specific compliance needs: Often pushes back toward self-hosted, with the budget to do it right.

The status page itself is rarely the hard part. The hard part is the operational discipline to keep it updated during real incidents. Hosted services help here by lowering the friction of posting an update — and friction matters when you’re already firefighting.

For monitoring data that drives whatever status page you choose, MyUptimeBot exposes results via webhooks and API. Self-hosters can pipe our results into their own page. Hosted-service users can wire our alerts into Statuspage / Statuspal / BetterStack via standard integrations.

The status page isn’t the monitoring system — it’s the public face of the monitoring system. Pick the cheapest approach that fits your customer expectations, and put the saved energy into the monitoring itself.

MyUptimeBot
Watching the internet

We build a friendly bot that watches your websites every 30 seconds and alerts you the moment something breaks. Notes here come from running that infrastructure, talking to the people who depend on it, and reading the postmortems no one publishes.

Stop finding out from customers.

One monitor, free forever. A friendly bot doing the worrying for you.