A practice prompt we wrote. No company or candidate report names it, so it carries no company tag.
How to answer
The function is short. The grade is whether “stable” survives restarts, other machines, other languages and a change to the percentage. Name all four first.
- Pin the contract.
is_enabled(flag, user_id) -> bool, where a flag holds an on switch, allow and deny lists, and a percentage. - Choose the hash deliberately. SHA-256 of
f"{flag.salt}:{user_id}"encoded as UTF-8, its first four bytes as a big-endian unsigned integer, then% 10_000for a basis-point bucket. Four bytes, because every client can hold them exactly as a non-negative number (getUint32in JavaScript, alongin Java); eight needBigIntin JavaScript, and Java reads them as a signedlong, where%returns a negative remainder: a different bucket. Rule outhash()andrandomby name. Salt per flag: without it, the same users get every new feature first. - Make the boundaries integer math. Store integer basis points and enable when
bucket < threshold, so zero means nobody and full means everybody. Floats fail quietly:0.29 * 100is 28.999999999999996. - Say what ramping promises. A user’s bucket never changes, so raising the threshold only adds users and lowering it removes the newest first. A new salt reshuffles everyone, so store it on the flag at creation, never derived from the name: a rename must move nobody.
- Fix the evaluation order. Off switch, deny list, allow list, then percentage. An unknown flag or missing ID gets the safe default, logged. Never hash an empty string, or every anonymous user lands in one bucket.
- Test the promises. The same answer in a fresh process, the right share over synthetic IDs, nobody lost as the threshold rises, and fixed
(salt, user_id, bucket)vectors that the server and mobile suites both assert, so a drifting port fails CI.
The trap is a flag that flickers: correct on your laptop, different after each deploy.
Follow-ups
What the interviewer may ask next, once your first answer is on the table.
- The server and the mobile app both evaluate the same flag. How do you make sure they give a user the same answer?
- Product wants to ramp the flag up over a week. What does your design promise the users who already have the feature?
- The customer wants everyone at one account to see the same thing. What do you hash now?
- A logged-out visitor is in the rollout, logs in, and the feature disappears. Why, and what do you hash for anonymous users?
- Two experiments must never share a user. Per-flag salts make cohorts independent, not disjoint. What does?
Where answers go wrong
- Bucketing with Python’s built-in
hash()on a string ID, which is salted per process (PYTHONHASHSEED), so a user’s answer changes on every restart and differs between servers. On an integer ID it returns the ID itself, so buckets follow signup order. - Hashing the user ID alone, so the same users are first into every rollout and every experiment shares one cohort.
- Comparing the bucket with
<=, so a flag set to zero still turns on for one bucket.
Answer this in two minutes
Write the answer you would say out loud. The clock starts with your first word.
Model answer
“Stable has to hold in four places: across restarts, across servers, across languages, and while the percentage changes. So the bucket has to be pure arithmetic on the flag’s salt and the user’s id, with no process state in it.