Professional Lab
A Canary Sizing Decision
Objective
Write a canary-sizing function that reasons about fleet size and risk tolerance, then confirm the existing evaluate_gate() logic still produces the right decision against a multi-device canary.
Builds on Production Automation.
Prerequisites
- Comfortable with evaluate_gate()'s threshold logic (Stage Gates: Validate, Then Expand -- or Abort)
- Comfortable with basic arithmetic reasoning (percentages, min/max bounds)
Scenario
The problem
Every canary in Production Automation and the Capstone was exactly one device, chosen without ever explaining why one was the right number. For a 3-device fleet, one canary is a third of everything. For a 200-device fleet, one canary tells you almost nothing before the other 199 go out. This lab writes the sizing logic those modules skipped, then checks that evaluate_gate() -- unchanged -- still works correctly once the canary itself is more than a single device.
A decision exercise, not a new rollout pipeline
Nothing here connects to NetBox, Git, or an actual staged rollout against NAPALM. This lab is deliberately narrow: one sizing function, and one confirmation that the already-proven gate logic holds at a different canary size.
Task
Write recommend_canary_size(fleet_size, min_canary=1, min_percent=0.1, max_canary=5) that:
- Computes
min_percentoffleet_size, rounded up (a canary of "2.3 devices" isn't meaningful — round up to guarantee at least that much real coverage). - Returns at least
min_canary, but never more thanmax_canary, even for a very large fleet.
Then, reusing evaluate_gate() exactly as Production Automation defined it (do not modify it), evaluate two 2-device canary scenarios:
- One where both devices pass.
- One where one device passes and one fails.
import math
MIN_CANARY = 1
MIN_PERCENT = 0.1
MAX_CANARY = 5
def recommend_canary_size(fleet_size, min_canary=MIN_CANARY, min_percent=MIN_PERCENT, max_canary=MAX_CANARY):
# Your code here.
...
# Reused verbatim from Production Automation -- do not modify this function.
def evaluate_gate(stage_result, threshold=1.0):
total = len(stage_result)
passed = sum(1 for r in stage_result.values() if r["applied"] and r["validated"])
pass_rate = passed / total if total else 0.0
return "PASS" if pass_rate >= threshold else "FAIL"Starter code. evaluate_gate() is given to you unmodified -- your task is recommend_canary_size() plus applying evaluate_gate() to the two scenarios described above.
Expected output
fleet_size=3 -> recommended canary size: 1
fleet_size=20 -> recommended canary size: 2
fleet_size=100 -> recommended canary size: 5
2-device canary, both pass: PASS
2-device canary, one fails: FAILReal, verified output. A 3-device fleet gets the floor (1); a 20-device fleet gets a real 10% (2); a 100-device fleet hits the ceiling (5, not 10) -- and evaluate_gate() produces the correct decision either way, unmodified.
Self-check only -- nothing here is submitted or graded. Compare against your own output manually.
Solution
Try the task yourself first -- the full solution and explanation stay hidden until you click above.
Key takeaways
- A canary size of "one" was a choice Production Automation never explained -- this lab writes the reasoning that choice was standing in for.
- Rounding up (math.ceil) and enforcing both a floor and a ceiling are what keep a percentage-based rule sensible at both very small and very large fleet sizes.
- evaluate_gate() needed zero changes to work correctly against a multi-device canary -- its threshold logic was already general, just never exercised that way before.
- No real fleet, device, or rollout was involved -- this is a sizing and decision exercise only.
Related lessons
Staging the Blast Radius: nr.filter() as a Canary Gate
Where the canary concept comes from -- this lab asks how big it should actually be, a question that lesson's fixed canary size never raised.
Read lessonStage Gates: Validate, Then Expand -- or Abort
evaluate_gate() itself, reused verbatim in this lab -- not re-taught, applied to a multi-device canary for the first time.
Read lessonDone with this lesson?