feat(health): add multi-service health check endpoint#611
Conversation
- Create GET /api/health that checks Supabase (SELECT), MongoDB (admin ping), Redis (PING command), Firebase (init flag), and Polygon (env var presence) - Returns HTTP 200 with status "ok" when all critical services are up; HTTP 503 with status "degraded" when Supabase or MongoDB fail - Includes process uptime in every response - Replace the previous static /api/health stub in index.js with the new router - Add Docker Compose healthcheck on the api service using the new endpoint Closes KanishJebaMathewM#580
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughA new ChangesMulti-Service Health Check Endpoint
Sequence Diagram(s)sequenceDiagram
participant Client
participant healthRouter as healthRoutes
participant Supabase
participant MongoDB
participant Redis
Client->>healthRouter: GET /api/health
par Concurrent dependency checks
healthRouter->>Supabase: select from profiles
healthRouter->>MongoDB: admin().ping()
healthRouter->>Redis: ping()
end
Supabase-->>healthRouter: connected | failed | not_configured
MongoDB-->>healthRouter: connected | failed | not_configured
Redis-->>healthRouter: connected | failed | not_configured
healthRouter-->>Client: 200 ok or 503 degraded with services map and uptime
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
🎉 Thank you for your contribution! Your pull request has been received and will be reviewed shortly. If you enjoy the project, please consider giving the repository a ⭐. You can also follow my GitHub profile to stay updated on future open-source projects. Thanks for being part of the community! 🚀 |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR introduces a richer /api/health endpoint that reports dependency status and wires it into Docker Compose healthchecks.
Changes:
- Added a Docker Compose healthcheck for the API service hitting
GET /api/health - Introduced
backend/api/src/routes/healthRoutes.jsto check Supabase/Mongo/Redis + configuration flags - Replaced the inline
/api/healthhandler inindex.jswith the new router
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| docker-compose.yml | Adds container healthcheck that calls the API health endpoint |
| backend/api/src/routes/healthRoutes.js | New health route that probes backing services and returns a summarized status |
| backend/api/src/index.js | Registers the new health router and removes the old inline handler |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/api/src/routes/healthRoutes.js`:
- Around line 55-59: The Promise.all call that combines checkSupabase(),
checkMongo(), and checkRedis() lacks timeout protection, which means any hung
dependency check can block the entire health endpoint. Wrap each individual
dependency check function (checkSupabase, checkMongo, checkRedis) with an
explicit timeout mechanism that rejects if the check takes longer than a
specified duration (e.g., 100-200ms). Alternatively, wrap the entire Promise.all
with a timeout guard to ensure the health check completes within the 500ms
health probe expectation. Apply the same timeout protection to the duplicate
Promise.all call mentioned at lines 75-79.
- Around line 69-73: The criticalFailed variable currently only checks if
supabaseStatus or mongoStatus equals 'failed', but it should also treat
'not_configured' as a critical condition. Update the criticalFailed condition to
include checks for both 'failed' and 'not_configured' states for both
supabaseStatus and mongoStatus variables so that misconfigured critical
dependencies result in a degraded status and HTTP 503 response instead of HTTP
200.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4eab91a9-fa5e-4400-8602-9bef263199ab
📒 Files selected for processing (3)
backend/api/src/index.jsbackend/api/src/routes/healthRoutes.jsdocker-compose.yml
…D-SHELL in Docker healthcheck
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
backend/api/src/routes/healthRoutes.js (2)
73-74:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTreat
not_configuredcritical dependencies as degraded.Currently only
'failed'triggers degraded status. If Supabase or MongoDB is'not_configured', the endpoint returns HTTP 200, which hides critical dependency misconfiguration from readiness checks. This was flagged in a previous review and remains unresolved.🛡️ Proposed fix to include not_configured
+ const criticalUnhealthy = ['failed', 'not_configured']; const criticalFailed = - supabaseStatus === 'failed' || mongoStatus === 'failed'; + criticalUnhealthy.includes(supabaseStatus) || + criticalUnhealthy.includes(mongoStatus);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/api/src/routes/healthRoutes.js` around lines 73 - 74, The `criticalFailed` variable in the health check route currently only checks if supabaseStatus or mongoStatus equals 'failed', but it should also treat 'not_configured' as a critical failure condition. Update the condition to include checks for both 'failed' and 'not_configured' statuses for both Supabase and MongoDB, so that misconfigured dependencies are properly reported as degraded instead of returning HTTP 200 and hiding the configuration issue from readiness checks.
8-15:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winClear timeout timer to prevent resource leak.
The
setTimeouttimer is never cleared when the promise resolves first. While not critical for infrequent health checks, this creates a minor resource leak.🧹 Proposed fix to clear timer
function withTimeout(promise) { + let timer; return Promise.race([ promise, new Promise((_, reject) => - setTimeout(() => reject(new Error('timeout')), CHECK_TIMEOUT_MS) + timer = setTimeout(() => reject(new Error('timeout')), CHECK_TIMEOUT_MS) ), - ]); + ]).finally(() => clearTimeout(timer)); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/api/src/routes/healthRoutes.js` around lines 8 - 15, The withTimeout function creates a setTimeout that is never cleared when the main promise resolves first, causing a resource leak. Store the timeout ID returned by setTimeout and use clearTimeout to clear it after the Promise.race completes. This can be done by adding a .finally() block or by wrapping the entire Promise.race result to ensure the timer is cleared regardless of which promise wins the race.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/api/src/routes/healthRoutes.js`:
- Line 6: The CHECK_TIMEOUT_MS constant is set to 3000ms, which exceeds the
performance requirement of 500ms for total health check completion. Reduce the
value of the CHECK_TIMEOUT_MS constant from 3000 to approximately 300-400ms to
ensure individual health checks complete quickly enough that the total endpoint
response remains within the 500ms budget, accounting for parallel execution and
orchestration overhead.
---
Duplicate comments:
In `@backend/api/src/routes/healthRoutes.js`:
- Around line 73-74: The `criticalFailed` variable in the health check route
currently only checks if supabaseStatus or mongoStatus equals 'failed', but it
should also treat 'not_configured' as a critical failure condition. Update the
condition to include checks for both 'failed' and 'not_configured' statuses for
both Supabase and MongoDB, so that misconfigured dependencies are properly
reported as degraded instead of returning HTTP 200 and hiding the configuration
issue from readiness checks.
- Around line 8-15: The withTimeout function creates a setTimeout that is never
cleared when the main promise resolves first, causing a resource leak. Store the
timeout ID returned by setTimeout and use clearTimeout to clear it after the
Promise.race completes. This can be done by adding a .finally() block or by
wrapping the entire Promise.race result to ensure the timer is cleared
regardless of which promise wins the race.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 41570f96-373e-4d3d-a212-e21ac771b9a6
📒 Files selected for processing (2)
backend/api/src/routes/healthRoutes.jsdocker-compose.yml
🚧 Files skipped from review as they are similar to previous changes (1)
- docker-compose.yml
…ot_configured as degraded
|
CI failures: Flutter Customer and Driver checks are pre-existing failures on main itself |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/api/src/routes/healthRoutes.js`:
- Line 6: The CHECK_TIMEOUT_MS constant at line 6 parses the environment
variable without validating the result, which can lead to invalid timeout values
like NaN, negative numbers, or Infinity. After parsing the
HEALTHCHECK_TIMEOUT_MS environment variable with Number(), add validation to
ensure the resulting value is a valid, positive, finite number. If the parsed
value fails validation (is NaN, negative, or not finite), fall back to the
default value of 400. This ensures the timeout configuration is always valid
before being used in health check operations.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: d4295d89-9f82-4fd2-9d6c-425ac3e3b082
📒 Files selected for processing (1)
backend/api/src/routes/healthRoutes.js
122d7d5
into
KanishJebaMathewM:main
|
🎉 Thank you for your contribution! Your pull request has been merged successfully. We appreciate your work and look forward to your future contributions. 🚀 |
What
Adds
GET /api/healththat checks each backend dependency and returns a structured status report.Response shape
Healthy (HTTP 200):
{ "status": "ok", "services": { "supabase": "connected", "mongodb": "connected", "redis": "connected", "firebase": "configured", "polygon": "configured" }, "uptime": 1234.5 }Degraded (HTTP 503) when Supabase or MongoDB fail — Redis, Firebase, and Polygon failures are non-critical.
Service checks
SELECTon profiles tableadmin().ping()PINGcommandPOLYGON_RPC_URLenv var is setChecks are lightweight and run in parallel via
Promise.all.Files changed
backend/api/src/routes/healthRoutes.js(new)backend/api/src/index.js— replace static health stub with new routerdocker-compose.yml— add healthcheck on theapiserviceCloses #580
Summary by CodeRabbit
Release Notes
New Features
/api/health) to run checks against core backend services in parallel and report overall status asokordegraded(returning503when critical dependencies are unavailable), including uptime./api/health/livethat always returns200withstatus: okand uptime.Infrastructure
/api/health/liveto better detect availability.