SA Pro Lab 04 — Blue/green: shift traffic with a weighted forward
Scaffold: 3/5. The VPC, the load balancer, both versions of the service, and blue’s target group are all built. You build the piece that makes it blue/green rather than just blue: green’s target group, and the weighted forward that gives the new version its first 10% of real traffic.
The scenario
A service is live behind an Application Load Balancer. The team has a new version deployed and tested — green — but it has never seen production traffic, and nobody wants to find its first bug at 100%. The classic answer is a canary: give green a small slice of real requests, watch it, then shift the weights in steps until blue drains to zero. If green misbehaves at any step, rollback is the same weight change in reverse: no redeploy, no rebuild, seconds not minutes.
The two versions here are Lambda functions that announce their colour, because the lesson is the routing, not the fleet. The same listener mechanic shifts traffic between two ASGs, two ECS services, or an on-prem target and a cloud one during a migration cutover.
The requirement
Out of 100 requests to the load balancer, roughly 90 should be answered by blue and roughly 10 by green.
What’s provided
src/template.yaml— a small VPC, an internet-facing ALB, the blue and green functions, invoke permissions for both, and blue’s target group. The listener forwards 100% of traffic to blue. TheTODOblock marks the gap.solution/template.yaml— the reference answer.scripts/— deploy, test, and teardown.
Your task
Two edits in src/template.yaml:
- Give green a target group mirroring blue’s (
TargetType: lambda, the green function as its one target,DependsOnthe green invoke permission). - Rewrite the listener’s default action as a weighted forward: a
ForwardConfigwith blue at weight 90 and green at weight 10, andTargetGroupStickinessConfigdisabled. Weights are relative, not percentages; using numbers that sum to 100 keeps them readable.
Run it
# Defaults: stack sa-pro-lab-04, region ap-southeast-2.
./scripts/deploy.sh # deploys src/template.yaml
./scripts/test.sh # sends 100 requests and counts the colours
./scripts/teardown.sh # deletes everything
The ALB bills by the hour (a few cents), so tear down when you’re done. The deploy tags the stack for the lab reaper as a backstop.
What success looks like
./scripts/test.sh prints something like:
blue: 91 (expected roughly 90)
green: 9 (expected roughly 10)
PASS: the canary is live. Green is taking a minority share of real traffic,
and shifting further (or rolling back) is now a weight change, not a redeploy.
With the shipped template every request comes back blue, and the test tells you why.
Reveal the solution
SRC=solution ./scripts/deploy.sh && ./scripts/test.sh
What you just learned
- Blue/green needs two routable fleets and one dial. The ALB weighted forward is the dial: traffic moves between target groups by changing two integers, and rollback is the same change in reverse.
- The canary step exists so the new version’s first bug is found at 10% of traffic, not 100%. Watch green’s errors and latency at each step before shifting further.
- Stickiness and canaries fight each other. With stickiness on, returning clients are pinned to the side they saw first, and the observed split stops tracking the weights.
- Target groups decouple “what the fleet is” from “how traffic reaches it”. The same weighted forward shifts between Lambda functions, ASGs, ECS services, or IP targets — which is why the pattern shows up in migration cutovers, not just deployments.
Next
The rest of the SA Pro lab track is listed in labs/README-sa-pro.md.