Design a scalable expense rules engine
Design a Scalable Expense Rules Engine
Context
You are tasked with designing a scalable rules engine for corporate credit-card expense review. This engine will be part of a multi-tenant expenses API, serving numerous companies. Its primary function is to evaluate submitted expenses against a set of rules and flag items that require manager review.
Expenses are provided as a list of dictionary objects, where all keys and values are strings. Each expense is guaranteed to have identifiers and basic fields such as amount, currency, expense_type, vendor_type, merchant, and transaction_date. A trip_id field may optionally be present.
Core Requirements
The engine must initially support the following base rules:
- No restaurant expense over $75.
- No airfare expenses.
- No entertainment expenses.
- No expense over $250.
Inputs
The core function will accept:
expenses: A list of dictionaries, where each dictionary represents an expense. All fields within these dictionaries are string-typed and must be parsed and validated by the engine.rules: A list of rule definitions. The candidate is responsible for defining the structure and semantics of theseRuletypes.
Function Signature
You are to propose the design for a function with the following signature:
evaluateRules(rules: list<Rule>, expenses: list<Expense>) -> ReturnType
The ReturnType must be stable and backward-compatible for clients across many companies.
Design Goals
The system must meet the following design objectives:
- Rule Management: Support 100+ rules selected per manager/team. Allow new rules to be added and created via an API without breaking existing clients.
- Evaluation Semantics: Clearly specify how rules are evaluated, including:
- Priority and ordering of rules.
- Support for logical combinators (AND/OR/NOT) within rules.
- Decision on short-circuiting versus exhaustive evaluation.
- Strategy for conflict resolution across multiple rules.
- Explainability & Auditability: For every violation, provide a clear reason, associated rule metadata, timestamps, and information about which policy or entity triggered the violation.
- System Qualities: Address multi-tenant isolation, authorization, observability, idempotency, deterministic ordering, and resilience to partial failures.
- Data Models & Validation: Define core data models (e.g.,
Expense,Trip,Rule,Policy,RuleResult,EvaluationSummary). Describe the strategy for parsing and validating string-typed inputs like amounts, categories, and vendor types.
Extension: Aggregate (Group-By) Rules
Extend the engine to support rules that operate on aggregated data, such as trip-level totals. Examples include:
- A trip's total expenses must not exceed $2000.
- Total meal expenses per trip must not exceed $200.
The engine should evaluate both per-entity (expense) and aggregate (trip) rules in a single pass. Describe your aggregation strategy, including considerations for caching and incremental updates.
The ReturnType must be backward-compatible and capable of surfacing both expense-level and trip-level violations. For each violation, it should include:
- Entity type (expense or trip) and its identifiers (e.g.,
expense_id,trip_id). - Violated rule codes, severity, and human-readable messages.
- Machine-readable fields (e.g.,
observed_value,threshold,currency). - Support for pagination (cursor-based) for large result sets.
AI interview prep
Core dilemma
Balancing the extreme flexibility and dynamic nature of a multi-tenant, user-defined rules engine with the need for high-performance, consistent, and auditable evaluation across both individual entities and aggregate data.
3 tradeoffs and 3 stress tests locked
Interview prep
Unlock the interviewer X-Ray rubric, tradeoff matrix, stress tests, clarifying questions, and key concepts.
Design a scalable expense rules engine
Design a Scalable Expense Rules Engine
Context
You are tasked with designing a scalable rules engine for corporate credit-card expense review. This engine will be part of a multi-tenant expenses API, serving numerous companies. Its primary function is to evaluate submitted expenses against a set of rules and flag items that require manager review.
Expenses are provided as a list of dictionary objects, where all keys and values are strings. Each expense is guaranteed to have identifiers and basic fields such as amount, currency, expense_type, vendor_type, merchant, and transaction_date. A trip_id field may optionally be present.
Core Requirements
The engine must initially support the following base rules:
- No restaurant expense over $75.
- No airfare expenses.
- No entertainment expenses.
- No expense over $250.
Inputs
The core function will accept:
expenses: A list of dictionaries, where each dictionary represents an expense. All fields within these dictionaries are string-typed and must be parsed and validated by the engine.rules: A list of rule definitions. The candidate is responsible for defining the structure and semantics of theseRuletypes.
Function Signature
You are to propose the design for a function with the following signature:
evaluateRules(rules: list<Rule>, expenses: list<Expense>) -> ReturnType
The ReturnType must be stable and backward-compatible for clients across many companies.
Design Goals
The system must meet the following design objectives:
- Rule Management: Support 100+ rules selected per manager/team. Allow new rules to be added and created via an API without breaking existing clients.
- Evaluation Semantics: Clearly specify how rules are evaluated, including:
- Priority and ordering of rules.
- Support for logical combinators (AND/OR/NOT) within rules.
- Decision on short-circuiting versus exhaustive evaluation.
- Strategy for conflict resolution across multiple rules.
- Explainability & Auditability: For every violation, provide a clear reason, associated rule metadata, timestamps, and information about which policy or entity triggered the violation.
- System Qualities: Address multi-tenant isolation, authorization, observability, idempotency, deterministic ordering, and resilience to partial failures.
- Data Models & Validation: Define core data models (e.g.,
Expense,Trip,Rule,Policy,RuleResult,EvaluationSummary). Describe the strategy for parsing and validating string-typed inputs like amounts, categories, and vendor types.
Extension: Aggregate (Group-By) Rules
Extend the engine to support rules that operate on aggregated data, such as trip-level totals. Examples include:
- A trip's total expenses must not exceed $2000.
- Total meal expenses per trip must not exceed $200.
The engine should evaluate both per-entity (expense) and aggregate (trip) rules in a single pass. Describe your aggregation strategy, including considerations for caching and incremental updates.
The ReturnType must be backward-compatible and capable of surfacing both expense-level and trip-level violations. For each violation, it should include:
- Entity type (expense or trip) and its identifiers (e.g.,
expense_id,trip_id). - Violated rule codes, severity, and human-readable messages.
- Machine-readable fields (e.g.,
observed_value,threshold,currency). - Support for pagination (cursor-based) for large result sets.