Health Endpoint Improvements
Overview
Section titled “Overview”The health endpoints have been updated to provide better monitoring capabilities while maintaining reliable liveness checks. The key improvement is that health checks now return HTTP 200 for expected health outcomes (including degraded services) with detailed status information reflected in the JSON payload. Only unhandled internal errors will result in HTTP 500 responses.
🚨 Problem Solved
Section titled “🚨 Problem Solved”Before (Caused Liveness Check Failures)
Section titled “Before (Caused Liveness Check Failures)”- Health endpoints returned HTTP 503 when database was unhealthy
- Liveness checks would fail even when the service was running
- Container orchestration (Docker, Kubernetes) would restart healthy services
- Monitoring tools couldn’t distinguish between service down vs database issues
After (Reliable Liveness Checks)
Section titled “After (Reliable Liveness Checks)”- Health endpoints return HTTP 200 for expected outcomes (including degraded services)
- Database status reflected in payload for detailed monitoring
- Liveness checks pass when service is running (even with database issues)
- Readiness checks can inspect payload for database connectivity
- HTTP 500 only for unhandled internal errors
🔧 Technical Changes
Section titled “🔧 Technical Changes”1. HTTP Status Code Changes
Section titled “1. HTTP Status Code Changes”// Before: Variable status codesstatus: dbHealth.status === 'healthy' ? 200 : 503;
// After: 200 for expected health outcomes (including degraded services)status: 200; // Return 200 for completed health checks// HTTP 500 only occurs for unhandled internal errors2. New Service Status Field
Section titled “2. New Service Status Field”// Added to all health responsesserviceStatus: dbHealth.healthy ? 'healthy' : 'degraded';3. Consistent Response Format
Section titled “3. Consistent Response Format”Both /health and /api/health endpoints now follow the same pattern:
- HTTP 200 returned for expected health outcomes (including degraded subservices)
- HTTP 500 returned for unhandled internal errors or exceptions
- Service status in payload indicates overall health
- Database details provide granular status information
Note for Operators: Check the payload
serviceStatusfield for granular health information. HTTP 200 indicates the health check completed successfully, while HTTP 500 indicates an unexpected service failure that requires investigation.
📊 Response Examples
Section titled “📊 Response Examples”Healthy Service (Database Connected)
Section titled “Healthy Service (Database Connected)”{ "status": "ok", "timestamp": "2024-01-15T10:30:00.000Z", "service": "erp-unlocked-web", "uptime": 3600, "memory": { "used": 128, "total": 512 }, "database": "connected", "databaseStatus": "healthy", "databaseMessage": "Database healthy: 45ms response", "serviceStatus": "healthy"}Degraded Service (Database Issues)
Section titled “Degraded Service (Database Issues)”{ "status": "ok", "timestamp": "2024-01-15T10:30:00.000Z", "service": "erp-unlocked-web", "uptime": 3600, "memory": { "used": 128, "total": 512 }, "database": "disconnected", "databaseStatus": "timeout", "databaseMessage": "Database health check timed out", "serviceStatus": "degraded"}Service Error (Critical Failure)
Section titled “Service Error (Critical Failure)”{ "status": "error", "timestamp": "2024-01-15T10:30:00.000Z", "service": "erp-unlocked-web", "error": "Critical service failure", "serviceStatus": "degraded"}🎯 Use Cases
Section titled “🎯 Use Cases”1. Liveness Checks (Service Running)
Section titled “1. Liveness Checks (Service Running)”# Docker health checkcurl -f http://localhost:4321/health# Returns 200 - health check completed (service is running)# Note: 200 doesn't guarantee service is healthy, check payload for details2. Readiness Checks (Inspect Payload)
Section titled “2. Readiness Checks (Inspect Payload)”# Check if service is ready to handle requestscurl http://localhost:4321/health | jq '.serviceStatus'# Returns "healthy" or "degraded"3. Monitoring & Alerting
Section titled “3. Monitoring & Alerting”# Monitor database connectivitycurl http://localhost:4321/health | jq '.database'# Returns "connected" or "disconnected"
# Check overall service healthcurl http://localhost:4321/health | jq '.serviceStatus'# Returns "healthy" or "degraded"4. Container Orchestration
Section titled “4. Container Orchestration”# Kubernetes liveness probelivenessProbe: httpGet: path: /health port: 4321 initialDelaySeconds: 30 periodSeconds: 10
# Kubernetes readiness probereadinessProbe: httpGet: path: /health port: 4321 initialDelaySeconds: 5 periodSeconds: 5🔍 Database Status Categories
Section titled “🔍 Database Status Categories”The health endpoint now provides detailed database status information:
Status Types
Section titled “Status Types”healthy- Database responding normally (< 5s)warning- Database slow (> 5s but responding)critical- Database connection failedtimeout- Database health check timed outunavailable- Database connection unavailableunauthorized- Database authentication failederror- Database query or other error
Error Differentiation
Section titled “Error Differentiation”- Timeout errors - Properly identified and marked
- Connection errors - Network, refused, not found issues
- Authentication errors - Auth, permission issues
- Query errors - Syntax, invalid query issues
- Generic errors - Sanitized to avoid sensitive information exposure
🚀 Benefits
Section titled “🚀 Benefits”1. Reliable Liveness Checks
Section titled “1. Reliable Liveness Checks”- No more false failures due to database issues
- Container orchestration works correctly
- Service restarts only when actually needed
2. Better Monitoring
Section titled “2. Better Monitoring”- Granular status information for different failure types
- Service degradation clearly indicated
- Database connectivity separately monitored
3. Improved Debugging
Section titled “3. Improved Debugging”- Clear error categorization for faster troubleshooting
- Sanitized error messages for security
- Consistent response format across endpoints
4. Production Stability
Section titled “4. Production Stability”- Health checks won’t crash the service
- Authentication failures isolated from health monitoring
- Service remains accessible even during database issues
📋 Implementation Details
Section titled “📋 Implementation Details”Files Modified
Section titled “Files Modified”apps/webapp/src/pages/health.ts- Main health endpointapps/webapp/src/pages/api/health.ts- API health endpoint
Key Changes
Section titled “Key Changes”- HTTP 200 returned for expected health outcomes (including degraded services)
- HTTP 500 returned for unhandled internal errors or exceptions
serviceStatusfield added to all responses- Database status reflected in payload, not HTTP status
- Consistent error handling across both endpoints
Backward Compatibility
Section titled “Backward Compatibility”- Existing health checks continue to work
- New fields are additive (non-breaking)
- Same endpoint URLs maintained
🔧 Monitoring Integration
Section titled “🔧 Monitoring Integration”Prometheus/Grafana
Section titled “Prometheus/Grafana”// Custom metric for service statusconst serviceStatus = response.serviceStatus; // "healthy" or "degraded"const databaseStatus = response.databaseStatus; // Detailed DB statusDatadog/New Relic
Section titled “Datadog/New Relic”// Service health metricdogstatsd.gauge('service.health', serviceStatus === 'healthy' ? 1 : 0);dogstatsd.gauge('database.health', databaseStatus === 'healthy' ? 1 : 0);Custom Alerting
Section titled “Custom Alerting”// Alert on service degradationif (response.serviceStatus === 'degraded') { sendAlert('Service degraded - database issues detected');}🎉 Summary
Section titled “🎉 Summary”The health endpoints now provide:
- Reliable liveness checks (HTTP 200 for completed health checks, HTTP 500 for unexpected failures)
- Detailed health information in the payload (including
serviceStatusfield) - Database status monitoring without affecting service availability
- Better container orchestration support
- Enhanced monitoring capabilities for production environments
Key Insight: HTTP 200 indicates the health check completed successfully, while HTTP 500 indicates an unexpected service failure. Operators should check the payload serviceStatus field for granular health information rather than relying solely on HTTP status codes.
This solves the original production issue where authentication failures were causing health checks to fail, while also improving the overall monitoring and alerting capabilities of your application.