A status page reads, from the outside, like a weekend project. A page with a list of components, a table of incidents, a form to post an update, an email send when something changes. Most engineers who look at it estimate a few days, and the first version usually does take a few days. The part that does not show up in that estimate is everything that has to be true about the page for it to do its actual job, which is being believed during the one moment your customers are actively deciding whether to trust it.
This is not an argument that building your own is wrong. Plenty of teams should, and the reasons are specific. It is an argument for estimating the real thing, not the demo.
What the first version actually gets you
A static status page, a database table, and a form is genuinely useful for the smallest possible case: a solo developer or a two-person team who wants somewhere to type "API is down, investigating" during an outage instead of tweeting it. If that is the entire requirement, build it. A single HTML page with a JSON file you edit by hand and deploy is a legitimate status page for that scale, and it will outlast most engineering debates about whether it should exist.
The estimate stops being accurate the moment any of the following becomes true, which for a company with paying customers is usually within the first year:
The page needs to update itself. A status page someone has to remember to open and edit during an incident is a status page that stays green through outages nobody was awake for, or too busy firefighting to narrate. The fix is wiring the page to something that actually checks the service: a cron job hitting your health endpoint, comparing the result to what it expects, and writing to the incidents table when it changes. That is no longer a page, it is a small monitoring system, with its own failure modes (what happens when the checker itself goes down; how many consecutive failures before you call it an incident instead of a blip; what a flapping check does to your incident history).
Subscribers want to be told, not asked to check. The moment someone asks "can I get an email when something changes," you are building an email system: signup, double opt-in confirmation (skip this and your sending domain gets flagged as spam within a month), one-click unsubscribe, a queue so a burst of incident updates does not fire five hundred emails synchronously and time out your request, and enough restraint in what triggers a send that people do not learn to ignore you. None of this is hard individually. All of it together is a real subsystem, not a feature.
More than one thing can be down at once, independently. "API," "Dashboard," and "Webhooks" failing on different schedules is normal, and a status page that only has one overall state cannot represent it without either lying (calling the whole system down over one degraded component) or lying the other direction (calling everything fine because the homepage still loads). Per-component status is a real data model decision, not a UI tweak, once you have more than one thing to watch.
A customer asks to put it on your own domain. status.yourcompany.com instead of a subdomain of whatever you built it on is close to a requirement once you have customers who screenshot your status page into their own incident reports. That means TLS certificate provisioning per customer domain, which is a small infrastructure project on its own if you have never automated it (Let's Encrypt's ACME protocol, DNS or HTTP challenge handling, renewal before expiry, all needing to work unattended).
Someone asks "what was our uptime last quarter." History that survives longer than your database's default retention, rendered as an honest percentage rather than a number someone eyeballed, is a reporting feature most homegrown pages never get around to, right up until a customer's procurement team asks for it in writing.
The part that is easy to underweight: correctness under pressure
The features above are buildable. What is harder to plan for is that a status page's entire value depends on it being right exactly when the rest of your systems are not. A bug in a normal internal tool causes an annoyance. A bug in a status page (an incident that opens for a check that was actually fine, a maintenance window that fails to silence the alert it was supposed to silence, a status page that shows green because a query timed out and the frontend swallowed the error) causes people to stop trusting your incident communication at all, which is the one thing the page exists to earn.
That correctness bar is also why maintenance windows are more subtle than they look: a window needs to silence alerts for the components it names, without also hiding the underlying measurement (if the migration runs long, you need the monitor to still notice), and without silencing components outside the window that have nothing to do with the planned work. Getting that scoping wrong in either direction, either firing alerts during announced maintenance or staying silent on an unrelated real outage, is the kind of bug that only shows up during an actual incident, which is the worst possible time to discover it.
The part of the estimate that keeps growing after launch
The first version shipping is not the end of the cost, and this is the part that trips up teams who did estimate the build honestly and shipped something solid. A status page is one of the few pieces of internal software whose bug reports arrive during your worst days: the maintenance window that silenced the wrong component during a real migration, the email queue that backed up during a genuine incident and delivered the "resolved" notice four hours late, the TLS certificate that quietly expired on a customer's custom domain because the renewal cron job failed silently three weeks earlier and nobody was watching a system that was supposed to need no watching. None of these show up in a demo. All of them show up eventually, and by definition they show up at the moment the page has the least margin for error.
This is also why "we will build the simple version now and add the rest later" is a reasonable plan for the first year and a risky one to leave permanent. The simple version optimizes for the case where nothing goes wrong with the status page itself, which is exactly backwards: the entire reason a status page exists is to be correct on the day something else has already gone wrong.
The honest cost comparison
Building the full version, meaning checks, per-component status, subscriber email with proper deliverability handling, custom domain with automated TLS, and history that survives a quarter, is closer to several weeks of focused engineering time than a weekend, plus ongoing maintenance every time an edge case surfaces (and it will: a maintenance window that overruns, a check that flaps, a bounce-handling edge case in the email sends). For a team that is not in the business of building monitoring infrastructure, that is real opportunity cost against whatever the team's actual product is.
Buying starts at free, with checks from multiple regions, subscriber emails with confirmation and unsubscribe already handled, per-component status, and a custom domain on paid tiers, none of which requires estimating an email deliverability project as a side quest to your actual roadmap.
The honest case for building anyway: you have specific requirements a vendor's page will not fit (an unusual auth model for a private page, a data residency requirement, or you are building status pages as your actual product), or the volume of pages you would run makes the vendor's per-page or per-subscriber pricing genuinely worse than the engineering time, which happens at a scale most companies asking this question have not reached yet. Outside of those cases, the weekend-project estimate is almost always wrong by an order of magnitude once subscribers, components, and a custom domain enter the picture, and none of those three are optional for very long.
If you want a gut check on where an existing page (yours or a vendor's) actually stands against this list, the status page grader scores a public status page's URL against what a reader needs during a real incident, free, no signup required.