Design a Robust Feature Flag Evaluation Engine
Company: Cresta
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
You are given feature definitions and user records as JSON. Each feature flag has a `key`, an `enabled` switch, a `default` Boolean, and an ordered list of rules. Each rule has one or more conditions, a Boolean value, and may have a rollout percentage. A user has a stable `user_id` plus attributes such as country, plan, email, and support tier.
Design an evaluation engine with two operations: evaluate one flag for one user, and evaluate every flag for one user. Conditions within a rule use AND. Support exact equality, membership, anchored regular-expression matching, and a documented approximate-string operator. Treat a missing or null attribute as a non-match. A disabled flag returns its default without evaluating rules. If no rule matches, return the default. If several rules match, use the reported true-wins policy rather than sorting by rule name.
Percentage rollout must be deterministic for the same user and flag. Treat the bucketing function as an injected dependency that maps `(user_id, flag_key)` to an integer from 0 through 99; a rule with percentage `p` is eligible when its bucket is less than `p`.
Explain your data model, control flow, error handling, and test strategy. Also explain how you would distinguish an evaluator defect from a corrupted input record when a supplied expected-decisions file was generated before some user attributes were erased.
### Constraints & Assumptions
- Flag and user files fit in memory, but there may be thousands of users and multiple flags.
- Regular expressions are evaluated from the beginning of the attribute value.
- Rule names have no precedence semantics.
- Invalid operators or malformed rule shapes must produce an explicit validation error rather than silently changing a decision.
- The evaluator must not mutate the parsed flags or users.
### Clarifying Questions to Ask
- What exact behavior should the approximate-string operator provide?
- Is true-wins applied only among matched rules, and can a false rule ever override a true rule?
- Is the rollout bucket implementation supplied, or must its cross-language hash contract be specified?
- Should malformed data fail the whole file, one flag, or one user evaluation?
### What a Strong Answer Covers
- Separates parsing and schema validation from pure evaluation logic.
- Defines each operator and handles null or missing attributes consistently.
- Applies disabled flags, rule matching, rollout eligibility, true-wins, and defaults in the correct order.
- Makes rollout decisions stable by injecting or versioning the bucketing contract.
- Uses focused tests for conflicting rules, anchored regex behavior, dirty records, repeated evaluation, and boundary percentages.
- Diagnoses fixture drift independently from evaluator correctness.
### Follow-up Questions
1. How would you cache decisions without serving stale results after a flag update?
2. How would you add rule priorities while remaining backward compatible with true-wins flags?
3. What telemetry would help explain why a user received a particular decision without exposing sensitive attributes?
Quick Answer: Design a feature-flag evaluator for one or all flags, with ordered conditions, deterministic percentage rollout, defaults, validation, and a true-wins policy. Define operator and null behavior, keep inputs immutable, test conflicting rules and rollout boundaries, diagnose stale fixtures, and consider cache freshness, compatibility, and safe telemetry.