A site can be completely unreachable and produce not a single error report. That sounds contradictory until you notice that error tracking runs inside your application, and an application that is not running cannot report anything.
This is the failure that produces a weekend of downtime discovered by a customer on Monday. The dashboard was clean the entire time — not because nothing was wrong, but because the thing that reports problems was part of what had stopped.
Both tools are in the eight things I set up on every build, and they are there because neither substitutes for the other.
What does each one actually see?#
Error tracking watches from inside. Uptime monitoring watches from outside. That single difference determines everything each can and cannot detect.
| Failure | Error tracking | Uptime monitor |
|---|---|---|
| Unhandled exception | Yes | No |
| Failed database query | Yes | Sometimes |
| Server completely down | No | Yes |
| DNS expired or misconfigured | No | Yes |
| SSL certificate expired | No | Yes |
| Deploy that never completed | No | Yes |
| Slow but functioning | Partial | Yes |
| Wrong content served | No | With content checks |
The rows where error tracking says no are the ones that matter most, because they are the total failures. An exception affects one request and one user; DNS expiring affects everybody, and it is invisible from inside a process that is no longer being reached.
The reverse is equally true. An uptime monitor requesting your homepage every minute will never notice that checkout throws for customers in one country, because the homepage is fine and that is the only thing it looks at.
Why is "the site is down" invisible to error tracking?#
Because reporting an error requires code to run, and several failure modes prevent that entirely.
A container that will not start reports nothing — the crash happens before the error reporter initialises. A misconfigured DNS record means requests never arrive. An expired certificate means browsers refuse the connection before any request is made. A build that failed leaves the previous version serving, or nothing at all.
There is a subtler version worth knowing. Some deployments fail in a way where the platform serves an error page from its own infrastructure. Your application never runs, the platform returns a clean 500, and error tracking is silent because there is no application to report from.
The common property is that all of these are outside the application. Anything that prevents your code executing is by definition something your code cannot report.
There is a related blind spot worth knowing about even when the application is running normally. Error tracking depends on being able to reach its own service, so an outbound network problem or an expired ingestion key produces the same silence as a crash. Most SDKs fail quietly by design, on the reasonable grounds that a monitoring tool should never break the application it monitors — which means a broken error tracker looks exactly like a healthy one.
What should the uptime monitor actually check?#
Not the homepage. An endpoint that exercises the parts most likely to fail.
A homepage on a static site proves the CDN is up. It proves nothing about the database, the queue or any third party, all of which can be broken while that page renders perfectly.
Add a health endpoint that touches the real dependencies and returns a meaningful status.
// /api/health — cheap, but it actually touches things.
export async function GET() {
const checks = await Promise.allSettled([
db.$queryRaw`SELECT 1`, // database reachable
redis.ping(), // cache/queue reachable
storage.head('healthcheck.txt'), // object storage reachable
]);
const failed = checks
.map((c, i) => (c.status === 'rejected' ? NAMES[i] : null))
.filter(Boolean);
return Response.json(
{ ok: failed.length === 0, failed },
{ status: failed.length ? 503 : 200 }
);
} Two properties matter. It must be genuinely cheap, because it runs every minute forever — a check doing real work becomes a meaningful share of your database load. And it must return a non-200 status when something is wrong, since most monitors alert on status code rather than parsing a body.
Keep it unauthenticated but unguessable, or the monitor cannot reach it. And do not include version numbers or internal hostnames in the response — it is a public endpoint whether or not it is linked.
What else is worth monitoring from outside?#
Three things beyond "does it respond", each catching a failure the basic check misses.
Certificate expiry, with warning#
Most platforms renew automatically and occasionally do not. A check warning fourteen days before expiry turns a total outage into a task, and the failure is otherwise sudden and complete — every browser refuses to connect at the same moment.
Content, not just status#
A page returning 200 with an error message in the body is up as far as a status check is concerned. Asserting that expected text appears catches the deploy that succeeded and rendered nothing.
The critical path, not the front door#
If you can afford one synthetic check beyond the health endpoint, make it the flow that earns money — a login, a search, an add-to-cart. That is the difference between knowing the site responds and knowing it works.
Check from more than one region if the audience is spread. A site reachable from Europe and not from Asia is an outage for half the users and looks perfectly healthy from a single monitoring location.
Frequency deserves a moment of thought rather than being left at the default. Every minute is standard and means a failure is detected within roughly two minutes given the two-consecutive-failures rule. Every five minutes is cheaper and means a ten-minute outage may go entirely unnoticed, which for most businesses is the wrong trade — the monitoring costs nothing and the outage does.
What the interval genuinely affects is the health endpoint's load. A check every minute from three regions is over four thousand requests a day, each touching the database. That is trivial for a single query and becomes meaningful if the endpoint grows into something that does real work, which is the argument for keeping it deliberately cheap and reviewing it if it ever gets extended.
What is error tracking genuinely good at?#
The failures that affect some requests rather than all of them, which is most of what actually goes wrong day to day.
It sees the exception with a stack trace, the request that produced it, the user it affected, and how many others hit the same thing. That last part is what turns a report into a priority — one occurrence is noise, four hundred in an hour is the thing to fix now.
It is also the only one of the two that catches regressions introduced by a deploy. A release that breaks one flow while leaving the site up produces a spike in a specific error, which is a signal an uptime monitor structurally cannot generate.
Wire it up before launch rather than after the first incident. Retrofitting means the first real problem is diagnosed from a user's description rather than from a stack trace, which is a considerably slower and less pleasant way to work — and the first week after launch is precisely when the most problems surface, so it is the week you least want to be blind.
How do you avoid alert fatigue?#
Alert on the things a human should act on tonight, and route everything else somewhere it can be read tomorrow.
The failure mode is a channel producing forty notifications a day, all of which are ignored, including the one that mattered. Once a team is muting a channel the monitoring is decorative regardless of how good the tooling is.
- Page for total outage. The health check failing twice in a row, from two locations.
- Notify for a new error type, once, with a count. Not once per occurrence.
- Digest for known noise — a daily summary of things happening at a steady rate that nobody has fixed.
- Suppress the ones you cannot act on, such as errors from a browser extension or a bot probing for admin paths.
- Require two consecutive failures before an uptime alert, or every transient network blip pages somebody.
The rule I hold to: if an alert fires and the correct response is to ignore it, the alert is wrong. Either fix the underlying issue or stop alerting on it, because the third option — receiving it and ignoring it — trains everyone to ignore the next one too.
Where should alerts go?#
Somewhere a human reads within the response time you are promising, which is usually not email.
For a small project that means a phone. An SMS or a push notification for total outage, and a chat channel for everything else. Email alerts arrive alongside everything else in an inbox and are read whenever the inbox is read, which is the wrong latency for a site being down.
The question worth answering explicitly at handover is who receives these after the project ends. An alert routed to a developer who is no longer engaged is worse than no alert, because everyone believes monitoring exists.
And test the delivery path. An alerting configuration that has never fired is untested, exactly like an untested backup — trigger it deliberately once and confirm the message arrives where you expect.
What does it cost?#
Nothing, at the scale most projects operate at.
Error tracking free tiers cover thousands of events a month, which is more than a healthy application produces. Uptime monitoring free tiers cover several checks at one-minute intervals. Both only start costing money at volumes that imply the project can afford them.
The real cost is attention: configuring the health endpoint, setting sensible thresholds, and tuning the noise in the first fortnight. Perhaps half a day, once, and it stays useful indefinitely.
Set against the alternative — a client discovering their own outage, or a broken checkout running for a week — this is among the cheapest things on the whole build list.
The failures that hurt most produce silence rather than noise, and silence has to be checked for deliberately.
How do you make errors useful rather than numerous?#
Raw exception reports are a list of things that went wrong. What you want is a short list of things to fix, and getting there takes a small amount of configuration.
Attach the release#
Every error should carry the version it occurred in. Without it, a spike after a deploy and a spike from a traffic increase look identical, and the first question during an incident — did we cause this — has no answer.
Attach the user, carefully#
An identifier is enough. Knowing that four hundred errors come from three users is a completely different problem from four hundred users hitting it once, and the two need opposite responses. Send an id rather than personal data, since the error tracker is a system holding production information.
Filter the noise at the source#
Browser extensions, bots probing for admin paths, and network errors from users navigating away all generate reports that are never actionable. Filtering them client-side keeps the signal readable and the quota useful.
Group deliberately#
Default grouping sometimes splits one bug across a dozen entries because a value appears in the message. Fixing the fingerprint so they group correctly turns twelve small problems into one real one, which is the version you will actually prioritise.
The measure of whether this is configured well is whether the dashboard is worth opening. If it holds two hundred untriaged entries nobody is reading it, and an important new error will arrive into a list already being ignored.
What should happen when an alert fires?#
Something written down, because the moment an alert arrives is the worst time to decide what to do about it.
Confirm it is real#
One failed check from one location is frequently the monitor rather than the site. Two consecutive failures from two regions is real. Building that into the alerting threshold rather than into a human judgement saves the false alarms.
Check the platform first#
A meaningful share of outages belong to somebody else. The host status page takes ten seconds and occasionally ends the investigation, which is worth doing before opening a terminal.
Check what changed#
Most incidents follow a deploy. The most recent release, and whether rolling back is available, is the second thing to look at — and rollback being an available option is what makes this a calm question rather than a frightening one.
Tell somebody#
A client hearing about an outage from you is a different conversation from one hearing about it from their own customers. Even a holding message — we know, we are on it — changes the relationship considerably.
This is the "site is down" runbook from the handover document, and the reason it exists as a written thing is that all four steps are obvious in the abstract and easy to forget when a client is calling.
What about the third thing — logs?#
Different again, and worth naming because people sometimes treat it as covering both.
Logs are the record you read after you already know something is wrong. They are for diagnosis rather than detection, and nobody watches them continuously — a problem visible only in logs is a problem nobody knows about.
Where logs earn their place is answering "what happened around 14:32", which neither of the other two can. Error tracking shows the exception; logs show the sequence leading to it.
Structured logging with a request id threaded through is the version that pays off, because it lets you reconstruct one request across services. Unstructured text logs are searchable and considerably harder to reason about.
What is the minimum worth setting up?#
Four things, perhaps an hour in total, and they cover the overwhelming majority of what goes wrong.
- Error tracking in the application, with the release version attached so a spike can be tied to a deploy.
- An uptime check on a health endpoint that touches the database, from two regions, alerting after two consecutive failures.
- A certificate expiry warning at fourteen days.
- One synthetic check on the critical path — whatever flow the business depends on.
That is the version I put on every project including small ones. Anything beyond it — performance monitoring, distributed tracing, custom dashboards — is worth adding when there is a specific question it answers, and is overhead before that.
Conclusion#
Error tracking watches from inside and sees exceptions, regressions and the failures affecting some users. Uptime monitoring watches from outside and sees the failures that stop your code running at all. Neither can see what the other sees, which is why the question is not which to choose.
Point the uptime check at a health endpoint touching real dependencies rather than at the homepage, alert after two consecutive failures, and add certificate expiry warning. Attach release versions to errors so a spike is traceable to a deploy. Send anything urgent to a phone rather than an inbox.
Then tune the noise, because monitoring nobody reads is the same as no monitoring with an extra subscription. An hour of setup, close to nothing to run, and it is the difference between hearing about an outage from a dashboard and hearing about it from a customer.
One habit worth adopting alongside all of this: after any real incident, spend ten minutes asking which of the two tools noticed it, and how long it took. If the answer is that neither did and a user reported it, that is a gap with a specific shape — a check that does not exist, or a threshold set too loosely. Incidents are the only reliable source of information about what your monitoring is missing, and the information decays quickly if nobody writes it down.