Phase 5: DevOps & Deployment

Health checks, uptime monitoring & alerting

Advanced ~3 min read
Think of it this way A friendly analogy. Read this if the technical version feels dense. Show Hide

Imagine you’re running a super popular restaurant. To make sure every customer gets delicious food and a great experience, you need to know if everything is working perfectly behind the scenes.

First, think about the chefs in your kitchen. Each chef at their station – say, the grill chef or the dessert maker – needs to check on themselves. This is like a "health check" for a computer program. A grill chef might do a quick "liveness check" by just making sure their stove is turned on and isn't completely frozen or broken. If it is, the kitchen manager needs to know immediately so they can fix it or get a new stove. But a deeper "readiness check" is when the chef also makes sure they have all their ingredients prepped, their pans clean, and everything ready to actually cook a new customer’s order. If the chef isn’t truly ready, the kitchen manager won't send new orders to them; they’ll send them to another ready chef or ask customers to wait a moment. This makes sure new requests only go to parts of your program that are actually prepared to handle them.

Now, you, as the restaurant owner, can’t be in the kitchen all the time. So, you hire a "secret shopper." This person is like an "uptime monitoring" service. They pretend to be a regular customer and try to order food from your restaurant at different times of the day, from different locations – maybe from across town or even another city! They don't peek into the kitchen to see if the chefs are doing their internal checks. They just try to walk in, see if the "Open" sign is lit, if the doors are unlocked, and if they can place an order. This gives you an "outside-in" view, just like your real customers would experience.

If your secret shopper tries to order and finds the doors locked, or the menu blank, or the phone number disconnected, they immediately tell you. This is an "alert." Knowing instantly that your restaurant isn't accessible to customers means you can jump in, find out what happened, and fix it fast. So, when you build computer programs, thinking about these checks helps you make sure your creations are always ready for people to use, always serving up a great experience, and letting you know right away if anything goes wrong so you can be a hero and fix it.

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

python
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.