What a health check endpoint is for
A health check endpoint is a URL on your web app that answers one question: is this process able to serve requests right now? It is not a page for customers. It is for the machines and the people who keep the app running. A monitor calls the URL on a schedule, reads the response, and tells you if something is wrong.
Without one, your monitor can only see that the home page loads. That is useful, but the home page may pull in pages, caches and images that hide a real fault. A dedicated endpoint gives you a small, stable target that you control. You decide what it checks, and you know what a failure means.
It also helps you during a deploy. A new version that crashes on start will fail its health check straight away, which is far quicker than waiting for a customer to write in.
Keep it cheap: one fast check, not a full test
The endpoint will be called often, so it must be cheap. If a monitor checks once a minute, that is 1,440 requests a day from one monitor alone. Each request should finish in a few milliseconds and use almost no resources.
Do not run your test suite, render templates or walk through a user journey inside the health check. Those belong in your CI pipeline or in a separate end-to-end test that runs a few times a day. The health check should answer a narrow question and answer it quickly.
A good health check does three things:
- Returns straight away without waiting on slow work
- Checks that the process is running and can accept a request
- Returns a short body that a person or a script can read
Here is a minimal example in plain JavaScript using Node's built-in HTTP module. The same idea works in any language or framework:
const http = require('http');
const server = http.createServer((req, res) => {
if (req.method === 'GET' && req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('ok');
return;
}
res.writeHead(404);
res.end();
});
server.listen(3000);
This endpoint proves the server is up and routing requests. For many small sites, that is enough.
Whether to check the database
This is the question people ask most often. The honest answer is that it depends on what your app cannot do without.
If the app serves cached or static content and the database is only needed for logins or checkout, a database failure should not take the whole health check down. In that case, check the database separately, or leave it out and let your error tracking pick up failed queries.
If every page depends on the database, a check that opens a connection and runs a trivial query can be useful. Keep the query simple, such as selecting a constant, and set a short timeout. A database that takes ten seconds to answer is a fault, and the check should fail rather than hang.
There is a trade-off to keep in mind. A database check tells you more, but it also makes the endpoint depend on something outside the app. If the database is slow for a minute, you will get an alert even though the web process is fine. Decide which kind of alert you want before you build the check.
Status codes to return and why
Monitors mostly read the status code, so get it right.
- 200 OK means the app is up and its checks passed. Return this only when the app can do its job.
- 503 Service Unavailable means the app is up but cannot serve requests properly, for example because a required dependency has failed. It tells the monitor and any load balancer that this instance should not receive traffic.
- 404 Not Found is wrong for a health check. If the route is missing after a deploy, you want a clear fault, not a quiet page that looks like it exists.
- 500 Internal Server Error suggests the health check itself crashed. Some teams use it, but a dedicated 503 with a reason is easier to read.
Keep the status code as the main signal. A monitor should not need to parse the body to know whether the app is healthy. The body is for people who open the URL in a browser or read the logs.
If the endpoint redirects, follow the redirect only if you have chosen to. Many monitors will treat a redirect as a success or a failure depending on settings, so it is simpler to have the health check respond directly on the path you monitor.
What not to expose in the response
The health check URL is public unless you put it behind something. Anyone can call it. So assume the response will be read by people you did not plan for.
Do not return:
- Version numbers or build hashes, which tell an attacker what to look for
- Hostnames, internal IP addresses or the names of services behind the app
- Database connection strings, error messages or stack traces
- Counts of users, orders or any business data
- Details of which checks passed or failed in a way that maps your internal layout
A plain ok or a short status word is usually enough. If you need detail for your own use, log it on the server, where only your team can read it. Keep the public response boring.
If you want the endpoint hidden entirely, restrict it to the monitoring service's addresses or to a path that only your team knows. That is a judgement for your setup, and it should be checked against your own risk, not taken from a general rule.
Pointing a monitor at it and choosing what to alert on
Once the endpoint works, add it as a monitor in AperioFlow. Enter the full URL, choose how often it should be checked, and make sure the alerts go to the people who will act on them. Alert emails go only to people in your organisation, so the list is yours to control.
For most small apps, alert on these:
- The endpoint returns something other than the expected status code
- The endpoint does not answer within your chosen timeout
- The endpoint fails for more than one check in a row, so a single blip does not wake anyone
Do not alert on every slow response. A health check that is a little slow once is normal. Alert when the pattern is clear, and let the status page and incident notes handle the rest.
When an alert fires, the first job is to find out whether customers are affected. Check the endpoint from a browser, look at recent deploys, and read the logs for the instance. If the fault is real, post an update on your status page so customers hear it from you first.
A health check is small, but it is the first thing that tells you the app is in trouble. Keep it cheap, return honest status codes, leave the internals out of the response, and point a monitor at it. The free plan includes 10 monitors, so you can start with the endpoint for your main app and add more as you need them.
Add the endpoint as a monitor and send alerts to your team. Start free at https://app.aperioflow.co.uk/#/signup