Challenge 3: Design a Health Check — Possible Solution ==================================================================== WHY AN UNCONDITIONAL 200 IS A WEAK HEALTH CHECK ----------------------------------------------------- A GET /health endpoint that simply returns 200 OK unconditionally, without checking anything, only confirms that the WEB SERVER PROCESS ITSELF is running and able to respond to an HTTP request — the most minimal possible signal. It says NOTHING about whether the app can actually do its real job: reach its database, run a real query successfully, or reach any other critical dependency it relies on. A web app whose process is alive but whose database connection is completely broken would still pass this kind of health check every time, giving the deployment pipeline a false "everything is fine" signal exactly when something is genuinely, seriously wrong. WHAT A BETTER HEALTH CHECK SHOULD ACTUALLY VERIFY, FOR A DATABASE- BACKED APP ------------------------------------------------------------------------- GET /health should attempt something that genuinely exercises the critical dependency, then return a status reflecting the REAL result: async function healthCheck(req, res) { try { await db.query("SELECT 1"); // a trivial, cheap real query res.status(200).json({ status: "healthy" }); } catch (err) { res.status(503).json({ status: "unhealthy", reason: "database unreachable" }); } } - Running a trivial real query (SELECT 1, or an equivalent minimal query) against the actual database connection confirms the app can genuinely reach and use its most critical dependency — not just that the process itself is technically alive. - Returning 503 (Service Unavailable) rather than 200 when the database check fails is what actually gives the deployment pipeline's automatic-rollback mechanism (this chapter's own section) something meaningful to react to — a health check that always returns 200 regardless of internal state gives the rollback mechanism nothing to ever trigger on, defeating its entire purpose. - The query should be DELIBERATELY TRIVIAL/cheap (not a real business query touching large tables) — a health check's job is to verify connectivity and basic responsiveness quickly and repeatedly, not to exercise expensive application logic on every single health-check poll. WHY THIS WORKS AS AN ANSWER ------------------------------ This directly addresses the chapter's own framing: "a robust pipeline defines a health check... and automatically rolls back... if that check fails." A health check can only serve that purpose if it's actually CAPABLE of failing in a way that reflects real problems — an unconditional 200 is structurally incapable of ever failing, no matter how broken the app actually is, making the entire automatic-rollback safety net this chapter describes completely inert in practice.