Design a scalable expense rules engine
Company: Rippling
Role: Software Engineer
Category: System Design
Difficulty: hard
Interview Round: Technical Screen
Design a rules engine to evaluate corporate credit-card expenses and flag items for manager review.
Initial requirements:
- Enforce base rules:
(
1) no restaurant expense over $75,
(
2) no airfare expenses,
(
3) no entertainment expenses,
(
4) no expense over $250.
- Inputs: expenses provided as a list of dictionary objects with string keys and values.
- Define types for rules (your choice) and propose the function evaluateRules(rules: list<Rule>, expenses: list<Expense>) -> ReturnType, where the return will be used by an expenses API serving many companies.
Design goals:
- Support 100+ rules selected per manager/team; allow adding new rules and rule creation via an API without breaking clients.
- Specify evaluation semantics: priority/ordering, combinators (AND/OR/NOT), short-circuiting vs exhaustive evaluation, and conflict resolution.
- Provide explainability/audit: per-violation reason, rule metadata, timestamps, and who/what policy triggered the violation.
- Address multi-tenant isolation, authorization, observability, idempotency, deterministic ordering, and resilience to partial failures.
- Define core data models (Expense, Trip, Rule, Policy, RuleResult, EvaluationSummary) and how string-typed inputs are parsed/validated (amounts, categories, vendor types).
Extension (aggregate rules):
- Add group-by rules such as:
(a) a trip’s total expenses must not exceed $2000, and
(b) total meal expenses per trip must not exceed $200. In the provided sample, trip "002" violates both.
- Extend the engine to evaluate both per-entity (expense) and aggregate (trip) rules in one pass; describe aggregation strategy, caching, and incremental updates.
- Propose a backward-compatible ReturnType that surfaces both expense-level and trip-level violations: entity type (expense/trip), identifiers (expense_id/trip_id), violated rule codes, severity, human-readable messages, machine-readable fields, and pagination.
Product questions to clarify:
- How are policies scoped (company/team/user) and how do overrides/precedence work?
- Currency/FX handling, locales, tax/tip treatment for meal caps, per-diem vs per-transaction limits.
- Category taxonomy (expense_type, vendor_type), who classifies, and how to handle unknown/mislabeled categories.
- Time windows (per trip/day/month), receipt requirements, exception workflows and approvals, SLAs/notifications.
- Versioning and rollout (A/B, canary), API rate limits, and return-type compatibility strategy over time.
Quick Answer: This question evaluates system-design and data-modeling competency for building a scalable, multi-tenant rules engine (category: System Design) that supports per-entity and aggregate (trip-level) evaluations, backward-compatible APIs, explainability/auditability, parsing/validation of string-typed inputs, and operational concerns like determinism, idempotency, and resilience. It is commonly asked to assess trade-off reasoning around extensibility, evaluation semantics (priority, combinators, short-circuiting), aggregation and caching strategies, and API/data-model stability, with a level of abstraction that is practical application focused while requiring conceptual architectural trade-offs and concrete design details.