Firmware Rollout Cohorts: Keep Canary Membership Stable Across Reboots
Keep canary membership stable by assigning it from a durable device identity and a versioned rollout rule, or by storing an authoritative server-side assignment. Do not draw a fresh cohort on every boot, reconnect or update check. A device that repeatedly reconnects should not receive repeated chances to enter an early rollout.
This article defines an original assignment contract, not a particular cloud service configuration. RFC 9019 supplies the update-role context; it does not prescribe the bucket algorithm below. No fleet experiment, assignment service or device test was executed.
1. Choose the owner of assignment
In RFC 9019’s architecture, the status tracker can determine which devices qualify for an update and track pending progress. That is a useful place to separate rollout policy from the firmware consumer’s installation work. It does not mean every updater provides a built-in campaign database.
| Assignment design | What must remain stable | Main qualification concern |
|---|---|---|
| Server stores a cohort per enrolled device. | Enrollment identity and assignment record. | Recovery and replicas must return the same authoritative assignment. |
| Server computes a deterministic bucket. | Identity, namespace, algorithm and encoding. | Every implementation must produce the same bucket from identical inputs. |
| Device computes a cached assignment. | Same inputs plus authenticated policy delivery. | Old firmware and reset paths must not reinterpret or replace the rule. |
Pick one authority. A server record and a local recomputation can coexist only if the precedence and mismatch behavior are explicit. If they disagree, hold automatic promotion and investigate; do not let whichever answer arrived last decide.
2. Define the identity lifecycle
Use the product’s approved enrollment identifier, with documented uniqueness and replacement behavior. A current IP address, reconnect timestamp or randomized link address is unsuitable if it changes during ordinary operation. A public identifier is also not an authentication credential.
Keep identity distinct from compatibility. RFC 9124’s Class ID describes devices that can accept compatible firmware. Many units may share that class. Assigning from the class alone could place every unit into the same bucket.
State whether a replacement main board becomes a new enrolled unit or inherits a controlled logical-device record. If a logical identity transfers, prevent the retired unit and replacement from being active under it simultaneously. A cloned filesystem must not clone an enrollment identity unnoticed.

3. Freeze the deterministic inputs
One illustrative contract computes SHA-256 over a versioned, unambiguous encoding of a rollout namespace and enrolled device identifier, interprets the first eight digest bytes as an unsigned big-endian integer, and takes its remainder modulo 10,000. The resulting bucket is in the range 0–9,999.
This is an original selection recipe, not an RFC requirement or security primitive for authorizing installation. Specify exact encoding, field lengths, string normalization and empty-input rejection. Length-prefixed fields avoid accidental ambiguity between different field pairs. Do not rely on a language’s process-randomized built-in hash.
Record an assignment revision separately from the rollout’s promotion revision. Changing the threshold should not change the namespace or hash inputs. If a new campaign intentionally reshuffles membership, give that decision a new namespace and retain the old assignment history.
A deterministic bucket does not promise an exact percentage or a representative sample. Finite populations vary; hardware batches and deployment environments can still be unevenly covered. Where coverage matters, define eligible strata and inspect the selected inventory before exposure.
4. Expand a cohort without reshuffling it
For a fixed bucket, use a cumulative threshold: admit the device when its bucket is less than the current threshold. A threshold of 500 selects buckets 0–499; increasing it to 2,000 preserves those selected buckets and adds 500–1,999.
| Illustrative bucket | Threshold 500 | Threshold 2,000 |
|---|---|---|
| 123. | Selected. | Still selected. |
| 500. | Not selected. | Selected. |
| 1,999. | Not selected. | Selected. |
| 2,000. | Not selected. | Not selected. |
These are hand-chosen boundary values, not observed device hashes. Validate threshold bounds from zero through 10,000. Define whether an explicit exception can add or exclude a device, who approves it, and how the exception is recorded.
Membership is only one eligibility gate. A selected device still needs the correct hardware, supported starting state, approved artifact and current operating conditions. If battery state temporarily blocks installation, retain its cohort assignment while reporting the separate eligibility reason.
5. Specify reset and replacement outcomes
| Event | Expected contract |
|---|---|
| Ordinary reboot or reconnect. | Same identity and assignment inputs produce the same bucket. |
| Firmware reinstall preserving enrollment. | Same assignment, even if local caches are rebuilt. |
| Reset that removes enrollment. | No anonymous reassignment; complete approved enrollment reconciliation first. |
| Main-board replacement. | Apply the documented new-identity or controlled-transfer rule. |
| Assignment algorithm migration. | Compare old/new records and explicitly authorize any membership change. |
Cache loss should trigger authoritative recovery, not a new random draw. If the assignment authority is unavailable, use the defined hold or previously validated policy; do not manufacture a new canary decision merely to continue polling.
6. Build a repeatability fixture
Create synthetic identifiers and fixed expected digest/bucket vectors. Run the same vectors through the server, device implementation if any, and maintenance tooling. Include empty identifiers, non-ASCII input if permitted, long fields, encoding-version mismatch and threshold boundaries.
Repeat the assignment after process restart, reboot, cache removal and reinstall. Test a duplicated enrollment identifier as a provisioning fault. Do not demand that different identities always have different buckets: collisions are expected when many identities map into 10,000 buckets.
Capture identity reference, assignment revision, namespace, bucket, threshold revision, exception and final eligibility reason without exposing credentials. Qualification should demonstrate repeatability and deliberate membership changes; it cannot establish firmware safety or complete fleet coverage.
Hypothetical reconnect bias
A gateway reconnects several times each day. A service that makes a new random canary choice on every check eventually admits it, while rarely connected gateways remain underrepresented. The apparent small rollout no longer represents one stable selected population.
With a fixed bucket and versioned threshold, reconnecting only repeats the same decision. Operators can expand exposure deliberately and explain exactly why each device became eligible. Deliver that assignment contract before relying on a canary label in a release dashboard.