FAILURE MAP
← Case archive

FA-73851 / Feature flag rollout bucketing / Open access

Percentage rollout gate: A user whose bucket equals the limit is enabled · case 01

Rollouts expose one extra basis point of traffic, and 0 percent still enables bucket zero.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The gate uses bucket <= limit, treating the limit as inclusive.

VERIFIED REPAIR

Enable only buckets strictly below the basis-point limit.

Unsuccessful approach: Subtracting one from the limit fixes equality but now drops the last legitimate bucket.

Case contract

bucket = int(first 8 hex digits of sha1(salt + "." + flag + "." + user), 16) % 10000; the rollout percentage pct has at most two decimals and becomes a basis-point limit round(pct * 100); the user is enabled iff bucket < limit. Return [bucket, enabled].

Why this case matters

Percentage gates must be reproducible across services so the same user sees the same state everywhere.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import hashlib
N = 1
observations = []
def solve(flag, user, salt, pct):
    limit = round(pct * 100)
    digest = hashlib.sha1((salt + '.' + flag + '.' + user).encode()).hexdigest()
    bucket = int(digest[:8], 16) % 10000
    return [bucket, bucket <= limit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),
  ('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],
 [('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 13', ['new-checkout', 'u70823', 'ramp-7', 31.8], [3179, True]),
  ('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False])],
 [('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
  ('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True])],
 [('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
  ('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),
  ('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False]),
  ('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, True])],
 [('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
  ('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),
  ('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),
  ('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
bucket exactly at limit is excluded (alice)[6665, True][6665, False]Failed
bucket one below limit is included (alice)[6665, True][6665, True]Passed
bucket exactly at limit is excluded (bob)[2755, True][2755, False]Failed
bucket one below limit is included (bob)[2755, True][2755, True]Passed
bucket exactly at limit is excluded (carol)[5745, True][5745, False]Failed
float truncation regression at 65.82 percent[6581, True][6581, True]Passed
hashed user sample 1[5052, True][5052, True]Passed
hashed user sample 2[928, True][928, True]Passed

SHA-256 / 362bca2e85ffc2d7eab73548ec9259e6afc4c78608b083e0d1c45d4f8b12f509

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import hashlib
N = 1
observations = []
def solve(flag, user, salt, pct):
    limit = round(pct * 100)
    digest = hashlib.sha1((salt + '.' + flag + '.' + user).encode()).hexdigest()
    bucket = int(digest[:8], 16) % 10000
    return [bucket, bucket < limit - 1]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),
  ('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],
 [('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 13', ['new-checkout', 'u70823', 'ramp-7', 31.8], [3179, True]),
  ('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False])],
 [('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
  ('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True])],
 [('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
  ('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),
  ('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False]),
  ('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, True])],
 [('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
  ('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),
  ('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),
  ('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
bucket exactly at limit is excluded (alice)[6665, False][6665, False]Passed
bucket one below limit is included (alice)[6665, False][6665, True]Failed
bucket exactly at limit is excluded (bob)[2755, False][2755, False]Passed
bucket one below limit is included (bob)[2755, False][2755, True]Failed
bucket exactly at limit is excluded (carol)[5745, False][5745, False]Passed
float truncation regression at 65.82 percent[6581, False][6581, True]Failed
hashed user sample 1[5052, True][5052, True]Passed
hashed user sample 2[928, True][928, True]Passed

SHA-256 / db0d2dac1e6e1e50d2094fefd418ab312864c8e2a497155dcd48ca2bef405a09

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import hashlib
N = 1
observations = []
def solve(flag, user, salt, pct):
    limit = round(pct * 100)
    digest = hashlib.sha1((salt + '.' + flag + '.' + user).encode()).hexdigest()
    bucket = int(digest[:8], 16) % 10000
    return [bucket, bucket < limit]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 1', ['search-v2', 'u55140', 's1', 100], [5052, True]),
  ('hashed user sample 2', ['new-checkout', 'u28082', 's1', 50], [928, True])],
 [('bucket one below limit is included (alice)', ['new-checkout', 'alice', 'prod', 66.66], [6665, True]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 13', ['new-checkout', 'u70823', 'ramp-7', 31.8], [3179, True]),
  ('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False])],
 [('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket exactly at limit is excluded (bob)', ['dark-mode', 'bob', 's1', 27.55], [2755, False]),
  ('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('hashed user sample 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
  ('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True])],
 [('bucket one below limit is included (bob)', ['dark-mode', 'bob', 's1', 27.56], [2755, True]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
  ('hashed user sample 16', ['new-checkout', 'u25854', 'prod', 0.57], [5842, False]),
  ('hashed user sample 23', ['new-checkout', 'u5210', 'prod', 58.78], [5878, False]),
  ('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, True])],
 [('bucket exactly at limit is excluded (alice)', ['new-checkout', 'alice', 'prod', 66.65], [6665, False]),
  ('bucket exactly at limit is excluded (carol)', ['search-v2', 'carol', 'prod', 57.45], [5745, False]),
  ('bucket one below limit is included (carol)', ['search-v2', 'carol', 'prod', 57.46], [5745, True]),
  ('float truncation regression at 65.82 percent', ['fast-pay', 'member13', 'prod', 65.82], [6581, True]),
  ('zero percent disables everyone', ['dark-mode', 'dave', 's1', 0], [4167, False]),
  ('full rollout enables everyone', ['dark-mode', 'erin', 's1', 100], [9606, True]),
  ('hashed user sample 21', ['new-checkout', 'u7954', 'prod', 59.72], [196, True]),
  ('hashed user sample 22', ['new-checkout', 'u52965', 'ramp-7', 70.89], [7088, True])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
bucket exactly at limit is excluded (alice)[6665, False][6665, False]Passed
bucket one below limit is included (alice)[6665, True][6665, True]Passed
bucket exactly at limit is excluded (bob)[2755, False][2755, False]Passed
bucket one below limit is included (bob)[2755, True][2755, True]Passed
bucket exactly at limit is excluded (carol)[5745, False][5745, False]Passed
float truncation regression at 65.82 percent[6581, True][6581, True]Passed
hashed user sample 1[5052, True][5052, True]Passed
hashed user sample 2[928, True][928, True]Passed

SHA-256 / c6ae7f8e4adce96a9565e5d6e5bf61bb5aee20d516a8f88ce35ff1aa95616c4d

Verification & scope

A deterministic toy flag-evaluation model with a stipulated contract; it does not reproduce any vendor SDK byte for byte. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:48:51.329529+00:00.

Case digest / 2d5182972023e65d10194443c0833a7e01aa758cdbf78eaf2d797d3d9b16eeef