This episode makes service quality measurable: defining SLIs and SLOs for HAProxy traffic, building alerting on error rate, latency, and resource saturation, and writing runbooks for traffic incidents and failover.

Metrics without targets are just numbers. Episode 21 gives those numbers meaning through SLOs (Service Level Objectives) and SLIs (Service Level Indicators), then connects them to alerting and runbooks.
You'll define SLIs for HAProxy traffic, set up alert rules for error rate, latency, and saturation, and write runbooks that let traffic incidents be handled calmly.
An SLI is a chosen quality measurement. For HTTP traffic through HAProxy, the most common SLIs:
The availability formula in PromQL:
1 - (
sum(rate(haproxy_frontend_http_responses_total{code=~"5.."}[5m]))
/
sum(rate(haproxy_frontend_http_requests_total[5m]))
)The formula above computes the proportion of 5xx responses to total requests over 5 minutes. The code=~"5.." code uses a label matcher to grab all 5xx responses.
SLOs set targets on SLIs:
The principle: SLOs must be realistic and agreed with the team and the service owner. Don't set targets that make the team embarrassed to acknowledge them.
Visualize SLOs with a Grafana panel: a time chart for error rate and a line for the SLO target. When the curve approaches the line, you're burning your error budget.
Alerts should only wake a human when truly necessary:
groups:
- name: haproxy.rules
rules:
- alert: HighErrorRate
expr: |
sum(rate(haproxy_frontend_http_responses_total{code=~"5.."}[5m]))
/ sum(rate(haproxy_frontend_http_requests_total[5m])) > 0.05
for: 10m
labels:
severity: critical
annotations:
summary: "Error rate above 5 percent for 10 minutes"for: 10m ensures the alert only fires if the condition persists for 10 minutes, avoiding false alarms from momentary spikes. Critical severity means immediate action.
The next two categories:
groups:
- name: haproxy.latency
rules:
- alert: HighLatency
expr: |
histogram_quantile(0.95,
rate(haproxy_frontend_http_request_duration_seconds_bucket[5m])) > 0.5
for: 15m
labels:
severity: warning
- alert: ConnSaturation
expr: haproxy_frontend_current_sessions / haproxy_frontend_max_sessions > 0.9
for: 10m
labels:
severity: warninghistogram_quantile(0.95, ...) > 0.5 fires an alert when 95 percent of requests are slower than half a second. ConnSaturation fires when connection usage approaches the maxconn limit.
Not every warning must wake someone:
This division keeps the team responsive without alert fatigue.
A runbook is a tested sequence of steps. Example for a dead HAProxy node:
journalctl -u haproxy and systemctl status haproxy.ip addr show.systemctl status haproxy --no-pager
ip addr show eth0 | grep 10.0.0.10
curl -s -o /dev/null -w "%{http_code}\n" http://10.0.0.10/systemctl status haproxy --no-pager confirms the process state before acting, and curl ... http://10.0.0.10/ confirms the service is still alive through the VIP.
When the error rate spikes because of traffic:
maxconn, backend CPU.When a backend disappears because of service discovery:
dig users-svc.internal.show servers state.resolvers and hold valid match.A runbook that isn't tested is nonsense. Practices that keep runbooks relevant:
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/ curl -s -o /dev/null -w "%{http_code}\n" is the fastest way to verify health during a drill or a real incident.
Episode 21 turns metrics into a measurable promise: SLIs chosen deliberately, SLOs that are agreed, alerting filtered so it isn't noisy, and runbooks that turn incidents into an executable routine.
Key takeaways:
for clause to avoid false alarms.In the next episode, the final one, we'll cover production hardening & best practices — a production checklist for security, availability, observability, and operational readiness, disaster recovery and configuration backup strategies, and how to document conventions and support boundaries.