Design an Extensible Tax Policy Engine
Company: Gusto
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
## Design an Extensible Tax Policy Engine
You already have a correct evaluator for one progressive-bracket policy. Design the surrounding tax engine so it can select different policies by tax year and filing status and can support approved alternatives such as a fixed-rate policy. Historical calculations must remain reproducible, and year- or status-specific conditionals must not be scattered through the evaluator.
Use this service-level contract as a starting point:
```text
calculate_tax(income_minor_units, tax_year, filing_status, policy_override=None)
-> {tax_minor_units, policy_version, breakdown}
```
`income_minor_units` is a nonnegative integer. A progressive policy consists of ordered bracket ceilings and rates; each rate applies only to income inside that bracket. A fixed-rate override applies one stated rate to the full taxable income. Explain any rounding rule you choose.
### Part 1 — Model and Select Versioned Policies
Describe the policy data, validation, and lookup for a requested year and filing status. Explain how the selected immutable policy reaches the evaluator and how the result retains an auditable per-bracket breakdown.
#### What This Part Should Cover
- Effective year and filing-status keys with an immutable policy version.
- Ordered, nonoverlapping bracket boundaries and a final open-ended bracket.
- Selection of exactly one approved version without mutable lookup during evaluation.
- Integer or decimal arithmetic with an explicit rounding boundary.
```hint Separate policy data from the evaluator
The calculation loop should consume a validated bracket list without knowing which year or filing status selected it.
```
### Part 2 — Add Custom Rate Strategies
Show how a caller can select a fixed-rate policy or another approved strategy without modifying the progressive evaluator. Define how an override is identified, validated, authorized, and recorded in the result.
#### What This Part Should Cover
- A common policy interface or tagged strategy representation.
- Clear fixed-rate semantics and valid rate bounds.
- No arbitrary executable caller code inside the service.
- Provenance for the override and deterministic re-execution.
```hint Extend the policy, not the conditional tree
Ask what all tax strategies must accept and return, then keep their internal rules separate.
```
### Part 3 — Version, Test, and Operate the Engine
Explain how policy corrections, new years, and regression tests are handled so an old calculation can be reproduced while new requests use the intended policy.
#### What This Part Should Cover
- Append-only or immutable policy versions and explicit selection rules.
- Boundary tests at every bracket edge, status, and rounding threshold.
- Properties such as nonnegative tax and monotonicity for valid progressive policies.
- Logs or records containing inputs, selected policy identity, breakdown, and engine version.
```hint Test one unit below, at, and above each boundary
Bracket bugs usually hide at the exact point where one marginal rate hands off to the next.
```
### What a Strong Answer Covers
- A policy-driven design that supports year and filing-status evolution.
- Correct marginal-bracket semantics and explicit money precision.
- Controlled extensibility for fixed or custom approved rates.
- Historical reproducibility, validation, audit records, and boundary-focused tests.
### Follow-up Questions
1. How should a corrected policy affect calculations already issued for that year?
2. What should happen when a caller requests an unsupported filing status?
3. Where should rounding occur if several jurisdictions are composed?
4. How would you compare two policy versions before activating the newer one?
Quick Answer: Design a versioned tax policy engine that selects rules by year and filing status while supporting progressive and fixed-rate strategies. Cover policy identity, reproducible historical calculations, extension boundaries, validation, rounding, testing, and controlled rollout.