FAILURE MAP
← Case archive

FA-73856 / Feature flag rollout bucketing / Open access

Percentage rollout gate: Float truncation shrinks fractional rollout limits · case 01

A 0.29 percent rollout admits only 28 basis points of buckets.

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

ROOT CAUSE

The limit is int(pct * 100), which truncates binary floating-point results such as 28.999999999999996.

VERIFIED REPAIR

Round pct * 100 to the nearest integer basis point.

Unsuccessful approach: Truncating pct before scaling discards the fractional percent entirely.

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 = int(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 32', ['fast-pay', 'u26409', 's1', 39.73], [3972, 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 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
  ('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True]),
  ('hashed user sample 47', ['dark-mode', 'u58180', 's1', 70.46], [7045, 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 17', ['search-v2', 'u90753', 'prod', 0], [9423, False]),
  ('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, 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]),
  ('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]),
  ('hashed user sample 32', ['fast-pay', 'u26409', 's1', 39.73], [3972, 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, False][6581, True]Failed
hashed user sample 1[5052, True][5052, True]Passed
hashed user sample 2[928, True][928, True]Passed

SHA-256 / 1fd6131c0f4c232ec5311daaaf61adccfef5e5bb1effa97e9fccf2f05a467189

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 = int(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 32', ['fast-pay', 'u26409', 's1', 39.73], [3972, 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 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
  ('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True]),
  ('hashed user sample 47', ['dark-mode', 'u58180', 's1', 70.46], [7045, 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 17', ['search-v2', 'u90753', 'prod', 0], [9423, False]),
  ('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, 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]),
  ('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]),
  ('hashed user sample 32', ['fast-pay', 'u26409', 's1', 39.73], [3972, 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 / 1fd575ba96856fccc6a8a5dd3e4abdded591e890c894dd4222250d83befe597f

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 32', ['fast-pay', 'u26409', 's1', 39.73], [3972, 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 11', ['search-v2', 'u91686', 'prod', 100], [5233, True]),
  ('hashed user sample 40', ['fast-pay', 'u536', 'prod', 9.61], [960, True]),
  ('hashed user sample 47', ['dark-mode', 'u58180', 's1', 70.46], [7045, 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 17', ['search-v2', 'u90753', 'prod', 0], [9423, False]),
  ('hashed user sample 51', ['new-checkout', 'u15929', 'ramp-7', 98.17], [9816, 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]),
  ('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]),
  ('hashed user sample 32', ['fast-pay', 'u26409', 's1', 39.73], [3972, 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 / 7f558978052e357763eba337b63bfd7270bd6b55ff77a2119a2effcfb628ce9a

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.335593+00:00.

Case digest / 9a0cab61f7ed7b4163f6ea813226fdd341fc449e2d6772d23c714f18326240da