What to Actually Alert On When You Self-Host
Most self-hosted monitoring alerts on the wrong things. Alert on symptoms users feel, not every metric, so the pages you get at 3am are always worth answering.
Alert on symptoms your users feel, not on every metric your server can emit. That is the whole discipline of good alerting, and almost everyone gets it wrong at the start. They wire up a monitor, see that it can watch CPU, memory, disk, load, and connection counts, and they alert on all of it. Then they get paged at 3am because CPU hit 90 percent for two minutes while nothing was actually wrong, they start ignoring alerts, and the one that matters slips past unread. I run monitoring across twenty companies alone, so I cannot afford noise. Every page has to be worth waking up for.
The problem with alerting on metrics
A metric crossing a threshold is not a problem. It is data. CPU at 90 percent might mean your box is dying, or it might mean it is doing exactly the work you built it to do, efficiently. Memory at 85 percent might be a leak, or it might be a healthy cache using RAM that would otherwise sit idle. If you alert on the raw number, you get paged for both, and the false pages train you to dismiss the real ones.
This is how alert fatigue kills a monitoring setup. It is not that the monitoring failed. It is that it cried wolf so often you stopped listening. The cost of a noisy alert is not the interruption. It is that it degrades every future alert, because you learn that alerts are usually nothing. Once that happens, your expensive monitoring is worse than none, because it gives you false confidence.
Alert on symptoms, not causes
The fix is to alert on what your users actually experience. Users do not feel CPU. They feel slow pages, errors, and outages. So those are what should page you.
- Is the site returning errors to real requests? Page me.
- Are response times so high that the app is effectively unusable? Page me.
- Is a user-facing endpoint down entirely? Page me.
- Is a critical background job, like a payment or an email send, failing? Page me.
These are symptoms. Each one means a person is having a bad time right now, which is the only thing worth waking up for. Notice that the external reachability check from your uptime monitoring setup is a symptom alert: it fires when the site is unreachable from outside, which is the purest user-felt problem there is.
Where causes belong: dashboards and warnings
CPU, memory, disk, and the rest are not useless. They are how you diagnose why a symptom is happening. But they belong on a dashboard you look at, or in a low-urgency warning channel, not in the pager that wakes you.
Draw the line by urgency.
- Symptoms that mean users are affected now: page, loud, immediate.
- Trends that mean trouble is coming: a warning, quiet, look at it during the day.
- Everything else: a dashboard you consult when investigating.
Disk filling up is a great example. Disk at 80 percent is not a page, because nothing is broken yet. It is a warning that in a few days you will have a problem, so you handle it on your schedule. Disk at 100 percent, where writes start failing and users see errors, is a symptom, and that pages you. Same metric, two different alert levels, decided by whether a user feels it yet.
Make every page actionable
A page you cannot act on is noise even if it is technically real. When an alert fires, there should be a clear next step. If the answer to "what do I do about this" is "nothing, it resolves on its own," it should never have been a page. This is where a runbook helps: each real alert links to what to check and what to do, so waking up leads to fixing, not to squinting at a dashboard trying to remember how this system works.
For a solo operator this matters double. I am the only one on call for everything, so an alert that pages me without a clear action is pure cost. I would rather miss a marginal signal than drown the important ones. When something does break, having the recovery already rehearsed, the same way I keep disaster recovery drilled, turns a page into a routine instead of a scramble.
Tune ruthlessly. Every time a page fires and turns out to be nothing, that alert is broken and you fix or delete it. Every time something breaks that did not page you, you add a symptom alert for it. Over time the pager converges on a small set of alerts that are almost always real, and that is the goal: a pager you trust enough to always answer.
I run this philosophy across my whole portfolio on HostSSH. Symptoms page, causes inform, every alert is actionable, and noise gets deleted on sight. Alert on what users feel. Everything else is a dashboard.