Health checks are internal endpoints within your application designed to report its operational status. These are typically simple HTTP GET requests, like /healthz or /readyz, returning a 200 OK status if everything is functioning, or a 5xx error if not. A 'liveness' check (e.g., /healthz) confirms the application process is running and not deadlocked, crucial for orchestrators like Kubernetes to restart failed containers. A 'readiness' check (e.g., /readyz) goes further, verifying that the application is ready to accept traffic, perhaps by checking database connections, external API dependencies, or internal queues. Load balancers and service meshes use these readiness checks to intelligently route requests only to healthy instances, ensuring a smooth user experience even during partial outages or deployments.
Uptime monitoring takes these internal health checks and extends them externally. An uptime monitoring service (e.g., UptimeRobot, Datadog Synthetics, Grafana Cloud) periodically pings your public health endpoints or main application URLs from various geographic locations. This provides a crucial outside-in perspective, confirming that your service is not only running internally but is also accessible and performing as expected for your users across the globe. It helps distinguish between an internal application issue and a broader network problem or DNS misconfiguration, giving you confidence that your service is truly available to the internet.
Alerting is the critical final step, ensuring that any detected issues—whether from failing internal health checks or external uptime monitoring—trigger immediate notifications to the right team members or automated systems. Effective alerting relies on well-defined thresholds (e.g., 3 consecutive failed health checks, or latency exceeding 500ms for 5 minutes) and actionable messages that specify the problem, its potential impact, and where to investigate. Integrating with communication channels like Slack, PagerDuty, or email, and implementing escalation policies, is vital to minimize downtime and prevent alert fatigue, enabling your team to respond proactively to incidents before they significantly impact users.
Key Takeaways
- Health checks provide internal application status for orchestrators and load balancers.
- Uptime monitoring verifies external accessibility and performance from a user's perspective.
- Alerting turns detected failures into actionable notifications for rapid incident response.
- Together, these ensure service reliability, enable automated recovery, and inform teams of critical issues.
Code Example
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/healthz', methods=['GET'])
def health_check():
# In a real application, you'd check database connections,
# external services, or critical internal components here.
# For a basic liveness check, just ensure the app is running.
# For a readiness check, ensure it can serve requests.
try:
# Example: check database connection (replace with actual logic)
# db.connection.ping()
status_code = 200
message = "Application is healthy and ready."
except Exception as e:
status_code = 503
message = f"Application unhealthy: {str(e)}"
return jsonify({"status": message}), status_code
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)How this code works
This Flask application serves as a foundational example for implementing health checks, a critical component of monitoring and alerting strategies. Its primary role is to expose an endpoint, /healthz, that external monitoring tools can query. By receiving a response from this endpoint, monitoring systems can determine if the application is not only running (liveness) but also capable of performing its essential functions (readiness), which is crucial for maintaining uptime and quickly identifying issues.
The code starts by importing Flask to build the web application and jsonify to format responses. app = Flask(__name__) initializes the application. The @app.route('/healthz', methods=['GET']) decorator maps HTTP GET requests to the /healthz path to the health_check function. Inside this function, a try...except block simulates real-world component checks (like database connections). If successful, it returns a 200 HTTP status code with a "healthy" message via jsonify. If an error occurs, it returns a 503 status with an error message. A subtle but important detail for deployment is app.run(host='0.0.0.0', port=5000). Setting host='0.0.0.0' allows the application to be accessed from any network interface, rather than just the local machine, ensuring external monitors can reach it.