A canary deployment sends a small fraction of traffic to a new version while the stable version handles the rest. If the canary fails, only the test fraction is affected.
For a runnable lab, see the canary-deployment directory in the IaC repository. It uses HAProxy weighted routing with raw C API servers.
HAProxy makes this pattern visible and controllable through weighted backend servers.
Weight Ratio
backend servers
balance leastconn
server v1 api_v1:8080 weight 10 check
server v2 api_v2:8080 weight 1 check
With weights 10 and 1, approximately 9% of requests reach v2. The weight proportion directly controls the blast radius:
- weight 10 : weight 1 = ~9% canary
- weight 10 : weight 10 = 50% (half the traffic, not a canary)
- weight 100 : weight 1 = ~1% canary
- weight 1 : weight 0 = disabled (v2 receives no traffic)
Start with a small fraction and increase as confidence grows.
Balance Strategy
The balance leastconn directive distributes requests to the server with the fewest active connections. This matters for long-lived connections like WebSockets or streaming responses.
For short-lived request-response workloads, roundrobin works just as well and is more predictable. Choose leastconn when backend response time varies significantly.
Health Checks Are TCP By Default
HAProxy’s check directive sends a TCP connection check by default. It only verifies that the port is open, not that the application is healthy.
A real canary should have a dedicated health check endpoint:
option httpchk GET /healthz
Without an HTTP health check, HAProxy may route traffic to a v2 that accepts TCP connections but returns 500s on every request.
Reading The Logs
Confirm which version served each request by checking response headers or structured logs. In a lab, the simplest approach is a version header:
HTTP/1.1 200 OK
X-Version: v2
If the canary is weighted at 10%, roughly 1 in 10 requests should show the v2 header.
Why Raw C In The Lab
The IaC repo canary lab uses a raw C HTTP server with BSD sockets. No framework, no dependencies. This is deliberate: deployment strategy labs should test traffic behavior, not framework configuration. If the lab requires understanding a web framework before testing the canary, it misses the point.
Production Translation
Lab canary:
HAProxy -> v1 (weight 10) | v2 (weight 1) -> manual observation
Production canary:
service mesh -> v1 (traffic) | v2 (traffic) -> metrics comparison -> auto-promote or auto-rollback
The lab teaches the weight concept. Production requires automated analysis and decision gates.
Acceptance Criteria
- Weighted traffic reaches both versions.
- Health checks catch an unresponsive canary before user impact.
- Request distribution matches the configured weight ratio.
- Rollback is a config reload away.
- Canary logs are distinguishable from stable logs.