DEV Community

DevHelm
DevHelm

Posted on • Originally published at devhelm.io

The Definitive Guide to Status Pages

Your users do not ask for a status page when everything is calm. They ask when the app is slow, login is failing, invoices will not load, or the API is returning 500s and your homepage still says nothing is wrong.

That is when you need one.

Without a status page, every outage becomes a guessing game. Customers cannot tell whether login is failing because of their network, their browser, or your platform. They open support tickets, refresh your homepage for an answer that is not there, and search social media or third-party outage sites because your company has nothing authoritative to link to.

A status page that is missing, outdated, or done wrong creates a different kind of damage. The marketing site still says everything is fine while invoices will not load. Support sends people to a page that shows green during a real incident. Engineering knows something is broken, but the public update is late, vague, or silent after the first post. Customers stop trusting the page. Your team answers the same questions in Slack, email, and tickets anyway.

That is the loop this guide breaks:

  • Customers file duplicate tickets asking "is it down?" because there is no single place to check.
  • Support improvises answers in chat, email, and macros while engineering is still debugging.
  • Users cannot tell what is broken, whether a workaround exists, or when they will hear from you again.
  • Enterprise buyers and procurement teams find no incident history when they evaluate your reliability.
  • Engineering loses focus posting one-off updates across channels instead of fixing the root cause.
  • A public page that lies during an outage damages trust more than saying nothing on the homepage.

This guide walks through how to build a page that stays accurate when it matters: what belongs on it, how to connect it to monitoring, how to communicate during incidents, where to host it, and how to set one up for Java Spring, Python FastAPI, and TypeScript web apps.

The durable pattern is monitoring and status communication in one system. Checks detect the issue, incidents track the response, component state follows monitor data, and customers get a clear public answer without someone manually toggling dropdowns at 3 a.m. DevHelm is built around that loop.

What is a status page?

A status page is a customer-facing page that reports the current and historical health of a product, API, application, or platform. It usually includes an overall status, a list of components, active incidents, scheduled maintenance, recent incident history, and subscription options.

Public vs internal

A public status page is written for customers. It should be plain-language, stable, and easy to share. It should avoid stack traces, internal hostnames, deploy IDs, and speculative root-cause detail. The audience wants impact, workaround, and timing.

An internal status page is written for employees, support, success, and sometimes enterprise customers behind authentication. It can include deeper component granularity, internal service names, owner teams, dependency status, and links to dashboards or runbooks.

Most SaaS companies need a public page first. Add an internal page when support needs a richer operational view than customers should see. DevHelm supports public pages and password-protected pages for internal audiences.

Page structure and setup

Components are the named systems customers care about: Website, Dashboard, API, Authentication, Billing, Webhooks, Search, File Uploads, EU Region, US Region, or Mobile App. Avoid mirroring your Kubernetes service list. Users do not know whether checkout-worker-v2 is important. They know whether checkout works.

Group components when the list gets long. Common groups include Product, APIs, Regions, Data Pipelines, and Third-Party Dependencies. A component group should make scanning easier, not turn the page into an architecture diagram.

Each component needs a small set of possible states:

State Meaning
Operational The component is working normally
Degraded performance The component works, but latency or errors are elevated
Partial outage Some users, regions, or functions are affected
Major outage The component is unavailable for most or all users
Under maintenance Planned work is in progress

Add incident history. Keep incident records browseable by date and linkable from support replies.

Add scheduled maintenance. Planned downtime should not look like a surprise outage. Announce the window, expected impact, affected components, and rollback criteria. During the window, the component can show Under Maintenance instead of Major Outage.

Add uptime or recent health where it helps. For infrastructure products and APIs, 30-day or 90-day uptime history by component is useful. For a simple B2B SaaS, component status and incident history may be enough. Do not add vanity graphs that make the page harder to understand during an active incident.

From structure to launch

Once components are defined, the launch workflow is the same whether you use DevHelm, UptimeRobot, Statuspage.io, Instatus, Cachet, or a custom build:

  1. Pick customer-facing components.
  2. Decide whether the page is public, internal, or password-protected.
  3. Choose a hosted status page, self-hosted status page, or DIY static page.
  4. Connect the page to monitoring so component state updates automatically.
  5. Add incident templates and an update cadence.
  6. Configure notifications for customers and internal teams.
  7. Put the page on a custom domain such as status.yourcompany.com.
  8. Publish it and link it from your website, app, docs, and support macros.

Incident communication

The first update should go out fast. It does not need a root cause. It needs acknowledgment, impact, and next update timing:

We are investigating elevated error rates on the API. Customers may see failed requests or delayed responses. Our team is actively investigating and will post another update by 14:30 UTC.

Use a predictable cadence. For severe incidents, update every 15 to 30 minutes even if the update is "we are still investigating." For lower-severity degradation, 30 to 60 minutes may be fine.

Keep tone direct and calm. Avoid jokes, blame, and vague reassurances. "Some users may be impacted" is weaker than "Customers in EU West may see 5xx responses when loading invoices." Say what you know, say what you do not know, and do not promise resolution before you have evidence.

Use the standard incident lifecycle:

  1. Investigating: you know something is wrong.
  2. Identified: you know the likely cause.
  3. Monitoring: a fix or mitigation is deployed.
  4. Resolved: metrics confirm recovery.

Write resolution updates with enough detail to close the loop:

The API error rate returned to normal at 15:12 UTC after we rolled back the deploy that introduced connection pool exhaustion. We are marking this incident resolved and will publish a follow-up after the post-incident review.

For major incidents, add a follow-up summary later. The status page timeline should stay concise during the event. A postmortem can carry root cause, contributing factors, and prevention work after the incident is over.

Notifications

Email is the default for customers. Atom/RSS feeds work for technical users and support teams that aggregate vendor updates. Webhooks fit machine-to-machine workflows: customer portals, ticket systems, or shared incident channels. Slack and Microsoft Teams help internal responders stay aligned, but they are not a replacement for email subscribers on a public page.

Avoid notification fatigue. Not every minor component blip needs to notify every subscriber. If you send five low-signal notifications during every deploy, customers will stop trusting the channel.

Templates

Templates make incident communication faster when they leave room for specifics. Use them as structure, then fill in exact impact.

For a first investigating update:

We are investigating [symptom] affecting [component/users/region]. Customers may see [visible impact]. We started investigating at [time] and will post the next update by [time].

For an identified update:

We have identified the issue as [confirmed cause]. The affected components are [components]. We are [mitigation/fix] and will post another update by [time].

For scheduled maintenance:

We will perform scheduled maintenance on [date/time] for [component]. Expected impact: [none/degraded/read-only/unavailable]. The maintenance window is [duration]. We will update this page when work begins, when validation starts, and when the window is complete.

Domains and branding

Use a custom domain for any serious public status page. status.yourcompany.com is easier to trust, remember, and link from your app footer, docs, help center, and support macros.

A hosted status page usually asks you to add a CNAME record. DevHelm provisions customer-owned status-page domains through the status page settings flow: add the hostname, copy the verification target, update DNS, and let the platform reconcile verification and SSL.

Branding should be restrained. Add your logo, page title, description, favicon, and brand color. Keep the design boring in the best way: fast loading, high contrast, mobile friendly, and readable during stress. Host the page separately from the product surface it reports on so it stays reachable when the app is down.

Connect monitoring

Manual pages drift. During an incident, the responder is checking logs, rolling back deploys, confirming region impact, and coordinating with support. Manually changing component states is easy to forget.

The better model is:

  1. HTTP, DNS, TCP, heartbeat, or browser monitors check user-visible paths.
  2. Monitors map to public components like API, Dashboard, or Billing.
  3. Component status is derived from check state.
  4. Incidents are created or suggested from monitor failures.
  5. Public updates are written once and pushed to the page and subscribers.
  6. Recovery follows the same monitor data that opened the incident.

DevHelm implements status pages around this model. Components can reference monitors, show uptime, be included or excluded from the overall status, and move through Operational, Degraded Performance, Partial Outage, Major Outage, and Under Maintenance.

Hosted vs self-hosted

There are three ways to create a status page: hosted, self-hosted, and DIY.

A hosted status page is the best default for most teams. Tools like Atlassian Statuspage, Instatus, Better Stack, UptimeRobot, and DevHelm handle hosting, SSL, page rendering, subscriptions, and incident pages. You should not be debugging your status page infrastructure during the same outage your customers are checking.

Standalone tools such as Statuspage.io are strong communication layers, but they do not monitor your product. You still need a monitoring source and the glue that keeps component states current. Bundled products keep monitoring, incidents, and the public page in one workflow.

Self-hosted status pages such as Cachet, Uptime Kuma, Gatus, or OpenStatus make sense when data residency, cost, or control is the primary requirement. DIY status pages are usually a mistake unless the requirements are tiny. A static page with a manual banner is better than nothing for a launch weekend, but it will not handle subscribers, feeds, incident history, custom domains, or automatic component updates without becoming a product of its own.

Option Choose it when Watch out for
Hosted bundle You want monitoring, incidents, status pages, and notifications together Make sure pricing does not scale painfully by subscriber or seat
Hosted standalone You already have a mature monitoring stack and only need communication You must maintain monitor-to-page automation
Self-hosted You need control and have ops capacity The status page becomes another service to run
DIY You need a temporary page today It will not stay accurate without engineering work

For a vendor-by-vendor breakdown, see the best status page software comparison and the Statuspage alternative page.

In practice: Spring, Python, TypeScript

The examples below show common patterns for each stack. Each framework exposes probes differently, and your status page maps those probes (and other customer-visible URLs) to named components.

What to monitor

A bare /health that always returns 200 only proves the process is running. A better one reflects real dependencies. Even then, no single endpoint proves login, billing, webhooks, or every API route work. Add monitors for each surface customers would notice.

Component What to probe When you need it
API Health URL plus at least one route customers use (safe read, auth token exchange, or versioned GET) Always for a backend product
Web App or Dashboard URL where users open the product (app.example.com or edge /health) SPA or server-rendered app on its own host
Website Marketing or docs homepage Public site on a different host or deploy
Authentication Login or token endpoint with a test credential Sign-in fails separately from generic API up
Webhooks or Background jobs Delivery-health or worker heartbeat Customers wait on async work or integrations

DevHelm follows the same pattern: https://api.devhelm.io/public/healthAPI, https://app.devhelm.io/healthDashboard, https://devhelm.ioWebsite on status.devhelm.io.

If a user would describe it as a separate broken thing, give it a separate component. Keep engineer-only probes (actuator, pod liveness, internal metrics) off the public page unless customers would notice them.

Status page for Spring Boot

A good Spring Boot health endpoint delegates to Actuator's aggregate health so that database or cache failures return 503, not just a JVM ping. Placing it on a public path like /public/health avoids WAF rules that sometimes block /actuator/* on public APIs.

The status page monitor hits this URL and asserts "status":"UP" in the response body.

@Hidden
@RestController
@RequiredArgsConstructor
public class PublicHealthController {

  public record HealthResponse(String status) {}

  private final HealthEndpoint healthEndpoint;

  @GetMapping("/public/health")
  public ResponseEntity<HealthResponse> health() {
    Status status = healthEndpoint.health().getStatus();
    int code = Status.UP.equals(status) ? 200 : 503;
    return ResponseEntity.status(code).body(new HealthResponse(status.getCode()));
  }
}
Enter fullscreen mode Exit fullscreen mode

Map this monitor to API. It is a strong baseline. Add authentication, webhooks, and business-route monitors from the table when customers depend on them.

Status page for Python FastAPI

A minimal FastAPI health route confirms the process is running. It is a liveness probe, not a guarantee that every route or worker is healthy:

    @app.get("/health")
    async def health() -> dict[str, Any]:
        uptime = time.monotonic() - _start_time
        return {
            "status": "healthy",
            "uptime_seconds": round(uptime, 1),
        }
Enter fullscreen mode Exit fullscreen mode

Map /health to API, then add monitors on routes customers call: webhook receivers, job triggers, or a safe versioned GET. If background workers affect customers, give them a separate component and heartbeat monitor.

Status page for React and Next.js

Web apps need monitors on the URLs customers open, not on React source files. Use the table above:

  • Web App — where users sign in and work (app.example.com or an edge /health)
  • Website — marketing or docs (example.com)
  • API — backend health endpoint from the Spring or FastAPI section

A passing Web App check means the page loads. Failed API calls from the browser show up on API, not on the web app monitor.

Set up with DevHelm

DevHelm bundles uptime monitoring, status pages, and alerting in one workspace. Status page components can follow monitor state automatically, so the page stays accurate during incidents without someone manually toggling dropdowns.

Dashboard setup

  1. Create monitors first. Add HTTP checks for the URLs your customers hit: API health, web app, login, billing, DNS, and SSL. If you are new to probe design, start with The Definitive Guide to Uptime Monitoring and API uptime monitoring.
  2. Open Status Pages in the dashboard at app.devhelm.io and create a page with a name, slug, and description.
  3. Components tab — add component groups if the list is long, then create components and map each one to a monitor. Customer-facing names go here. Internal service names stay in monitoring.
  4. Settings tab — choose public or password-protected visibility, set incident mode (AUTOMATIC publishes from monitor failures; MANUAL keeps you in control), add logo and brand colors, and attach a custom domain such as status.yourcompany.com.
  5. Subscribers tab — enable email subscriptions. Technical users can also follow the page Atom/RSS feed from the public URL.
  6. Incident Management tab — post updates during active incidents, or let automatic mode open incidents when mapped monitors fail. For update cadence and tone, see the Incident communication section above and Anatomy of a status page in the docs.
  7. Publish and link the page from your app footer, docs, help center, and support macros.

The dashboard tabs map to that workflow: Overview (summary), Components, Incident Management, Subscribers, and Settings.

CLI, YAML, and Terraform

For code-first teams, define monitors and status pages together in devhelm.yml and deploy with devhelm deploy. The statusPages section sits alongside monitors, alert channels, and notification policies in the same file. Full command reference: devhelm status-pages (create pages, components, groups, incidents, subscribers, and custom domains).

When a new Spring service, FastAPI route, or TypeScript app ships, add the monitor and status page component in the same pull request. See Monitoring as code for the workflow and Monitoring alerts for routing failures to the right channel.

Terraform users can manage pages with devhelm_status_page resources alongside monitors.

What to read next

Examples by product type

Status page examples are useful only when they match the product. A developer API, a B2B SaaS dashboard, and a consumer mobile app should not expose the same component list.

For an API company, use components such as API, Authentication, Webhooks, Developer Dashboard, Documentation, and Status Feed. For a B2B SaaS product, use Website, Web App, Login, Billing, Notifications, File Uploads, Reporting, and Integrations. For an infrastructure or platform product, use region and dependency-aware components: US East, EU West, Control Plane, Data Plane, API Gateway, and Third-Party Dependencies. For an internal status page, include more operational detail and keep it password-protected.

Pre-launch checklist

Before publishing, review the page as if you were a customer during an outage:

  • Is the URL obvious, branded, and linked from public places?
  • Are components named in customer language?
  • Are critical paths monitored from outside your infrastructure?
  • Does the page distinguish degraded performance, partial outage, major outage, and maintenance?
  • Can users subscribe by email or feed?
  • Does the first incident update template include impact and next-update time?
  • Are support and success teams trained to link the page instead of improvising answers?
  • Does the page remain available if the main app is down?

FAQ

What is a public status page?

A customer-facing page at status.yourcompany.com that shows current health, active incidents, maintenance windows, and incident history in plain language.

How do you create a status page?

Follow the Set up with DevHelm steps: create monitors, map them to components in the dashboard (or devhelm.yml), configure visibility and a custom domain, then publish. Docs: Quickstart and devhelm status-pages.

Should a status page be hosted or self-hosted?

Hosted is the best default because the page must stay available during incidents. Self-hosted works when you need control and have the team to operate it. DIY works only for short-lived or very simple needs.

What should incident communication include?

Every incident update should include impact, affected components, current status, what the team is doing, and when the next update will be posted. Avoid speculation until the root cause is confirmed.

What are status page best practices?

See the pre-launch checklist above.

Does DevHelm replace Statuspage.io?

For teams that want monitoring and status pages together, yes. Statuspage.io is a mature communication layer, but it does not run uptime checks. DevHelm bundles monitoring, status pages, incident updates, custom domains, alert channels, feeds, and dependency context in one product.

Create a hosted status page with DevHelm, or compare vendors in the best status page software guide.


Originally published on DevHelm.

Top comments (0)