Feature Flag Evaluation Engine
Reported by candidates from Cresta's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
The Cresta OA reported in July 2026 dresses up as a product-engineering puzzle, but it's a parsing and simulation job. You get five string tables and have to turn them into per-user flag answers. There's no clever algorithm here. The risk is small spec details: true-wins merging, empty rollout strings, FNV-1a hashing with 32-bit overflow, and the "*" query ordering. If you blank on any of them mid-assessment, StealthCoder is the invisible safety net that reads the problem and hands you a working solution. Still, know the shape before you open the invite.
The problem
Implement a feature flag evaluator over normalized rows derived from flag and user JSON data. The inputs have these forms: Each flags row is [flagKey, enabled, defaultValue], where the last two values are "true" or "false". Flag order is significant. Each rules row is [flagKey, ruleId, value, rolloutPercentage]. An empty percentage means no rollout gate; otherwise it is an integer from 0 through 100. Each conditions row is [flagKey, ruleId, attribute, operator, operand]. All conditions belonging to one rule are ANDed. A rule with no condition rows passes its condition group. Each users row is [userId, attribute1, value1, attribute2, value2,...]. Each queries row is [userId, flagKey]. The special key "*" requests all flags for that user. Condition Operators eq: the user value equals operand exactly. in: the user value equals one token in the comma-separated operand list. regex: the user value fully matches the valid anchored regular expression in operand. ~=: the lowercased ASCII operand is a substring of the lowercased ASCII user value. An absent user attribute makes its condition false. Judged user values are always non-null strings. Percentage Rollout For a rollout rule, build flagKey:ruleId:userId and compute its unsigned 32-bit FNV-1a hash: start at 2166136261; for each ASCII byte, XOR the hash with the byte, multiply by 16777619, and reduce modulo 2^32. The rule passes its rollout gate exactly when hash mod 100 < rolloutPercentage. Decision Rules A disabled flag returns its default and ignores every rule. For an enabled flag, a rule matches only when its condition group and optional rollout gate both pass. If no rule matches, return the flag default. If one or more rules match, return true when any matched rule has value true; otherwise return false. Return one string per query. A single-flag query returns flagKey=true or flagKey=false. An all-flags query returns those pairs in input flag order, joined by |. Function evaluateFeatureFlags(flags: String[][], rules: String[][], conditions: String[][], users: String[][], queries: String[][]) → String[] Examples Example 1 flags = [["new_nav","true","false"],["beta_banner","false","true"]] rules = [["new_nav","country_rule","true",""],["new_nav","plan_rule","false",""],["new_nav","vip_rule","true","100"]] conditions = [["new_nav","country_rule","country","eq","US"],["new_nav","plan_rule","plan","in","free,trial"],["new_nav","vip_rule","email","regex","^vip.*@example[.]com$"]] users = [["u1","country","US","plan","free","email","regular@example.com"],["u2","country","CA","plan","trial","email","vip42@example.com"],["u3","country","CA","plan","paid","email","guest@example.com"]] queries = [["u1","new_nav"],["u2","*"],["u3","new_nav"]] return = ["new_nav=true","new_nav=true|beta_banner=true","new_nav=false"] For u1, the country rule returns true while the plan rule returns false, so true-wins yields true. For u2, the plan rule and the 100% VIP rule both match, again yielding true; disabled beta_banner returns its default true. No rule matches u3, so new_nav returns its default false. Example 2 flags = [["search","true","false"]] rules = [["search","platform_team","true",""]] conditions = [["search","platform_team","team","~=","PLATFORM"]] users = [["u1","team","Core Platform"],["u2","team","Mobile"]] queries = [["u1","*"],["u2","search"]] return = ["search=true","search=false"] The ~= operator ignores ASCII letter case. Core Platform contains PLATFORM, while Mobile does not. Example 3 flags = [["gradual","true","false"]] rules = [["gradual","r1","true","30"]] conditions = [] users = [["u1"],["u2"]] queries = [["u1","gradual"],["u2","gradual"]] return = ["gradual=false","gradual=true"] The FNV-1a buckets for gradual:r1:u1 and gradual:r1:u2 are 64 and 21. Only 21 is below the 30% threshold. Constraints 1 <= flags.length <= 50 0 <= rules.length <= 1000 0 <= conditions.length <= 5000 1 <= users.length <= 10000 1 <= queries.length <= 500 Every flag key, rule ID, user ID, attribute name, user value, operand, and pattern is valid non-null ASCII text of length from 1 through 100. Flag keys, rule IDs within a flag, user IDs, and attribute names within a user are unique. Flag keys contain neither *, |, nor =. Each flag row, rule row, condition row, user row, and query row has exactly the shape described above, and every reference names an existing flag, rule, or user. Every boolean field is exactly "true" or "false". Each rollout percentage is empty or a base-10 integer from 0 through 100. Every in operand is a comma-separated list of non-empty tokens, and its compared user value contains no comma. Every regex operand begins with ^, ends with $, and is valid with the same full-match meaning in Python, Java, and C++14 ECMAScript regex; lookarounds and backreferences are excluded.
Reported by candidates. Source: FastPrep
Pattern and pitfall
It reduces to grouping plus evaluation. Build a map of flagKey to rules, and a map of (flagKey, ruleId) to its conditions. Build a map of userId to an attribute dictionary from the alternating pairs. Then for each query, walk flags in input order. Disabled flag returns default. Otherwise, a rule matches if every condition passes and the rollout gate passes. Any matched rule with value true wins, no match means default. The pitfalls are concrete. FNV-1a needs a multiply masked to 32 bits, which overflows in Java or JS if you're careless. Regex must fully match, so use a full-match call. The ~= operator lowercases both sides. A missing attribute is false. A rule with no conditions passes. Precompute indexes so 10000 users and 5000 conditions don't become nested scans. If you freeze on the hash or regex semantics live, StealthCoder is your hedge.
Drill it cold or hedge it with StealthCoder. Either way, don't walk into the OA hoping you remember the trick.
You can drill Feature Flag Evaluation Engine cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Made for the candidate who got the OA invite this morning and has 72 hours, not six months.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Cresta's OA.
Cresta reuses patterns across OAs. Made for the candidate who got the OA invite this morning and has 72 hours, not six months. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Feature Flag Evaluation Engine FAQ
What's the real trick in the Cresta feature flag problem?+
There isn't an algorithmic trick. It's careful simulation. Index rules and conditions by flag and rule ID, index users by attribute, then apply the decision rules exactly as written. Most failures come from small details, not from the structure.
How do I implement the FNV-1a hash correctly?+
Start at 2166136261. For each ASCII byte of flagKey:ruleId:userId, XOR the byte in, then multiply by 16777619 and mask to 32 bits. Use unsigned arithmetic or a 64-bit type. Then take hash mod 100 and compare it strictly less than the rollout percentage.
How should I handle the regex and ~= operators?+
Regex must match the whole user value, so use a full-match function rather than a search. For ~=, lowercase both the operand and the user value, then check substring containment. Both return false when the user lacks the attribute.
What edge cases break most solutions?+
An empty rollout string means no gate, not 0 percent. A rule with no condition rows passes. A disabled flag ignores all rules. A 0 percent rollout never passes. The "*" query must output pairs in flag input order joined by a pipe.
How do I prepare for this in 48 hours?+
Write a small version yourself with the three examples as tests. Hand-compute one FNV-1a hash to confirm your overflow handling. Practice building lookup maps from string tables. That covers nearly everything this problem tests.