PracHub
QuestionsCoachesLearningGuidesInterview Prep
|Home/System Design/Rippling

Design a scalable expense rules engine

Last updated: May 28, 2026

Quick Overview

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.

  • hard
  • Rippling
  • System Design
  • Software Engineer

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.

Related Interview Questions

  • Prevent Duplicate Payments Under High Load - Rippling
  • Design a personalized news aggregator - Rippling (medium)
  • Design a Scalable News Feed - Rippling (medium)
  • Design Scalable Expense Violation Processing - Rippling (hard)
  • Design several large-scale systems - Rippling (hard)
|Home/System Design/Rippling

Design a scalable expense rules engine

Rippling logo
Rippling
Sep 6, 2025, 12:00 AM
hardSoftware EngineerTechnical ScreenSystem Design
178
0

Design a Rules Engine for Corporate Credit-Card Expense Review

Context

We offer a corporate credit card that employees use for business expenses. Managers set policies on these cards so employees don't misuse the card or exceed allowances. You are designing the rules engine that powers this product: it evaluates submitted expenses against a set of rules and flags items for manager review.

The engine is part of an expenses API serving many companies (multi-tenant). You're encouraged to ask product-oriented questions and to state your assumptions as you go.

This is a two-part problem. We'll start with basic per-expense rules (Part 1), then add aggregate trip-level requirements (Part 2) — so design for flexibility from the start. In both parts, discuss the return type before you write code.

Input format

Expenses are provided as a list of dictionary/hashmap objects with string keys and string values (so fields must be parsed/validated). Each expense looks like this:

expense_idtrip_idamount_usdexpense_typevendor_typevendor_name
00100149.99suppliesrestaurantOutback Roadhouse
002001125.00suppliesretailerStaples
003002153.00mealsrestaurantOlive Yurt
0040021996.00airfaretransportationSoutheast Airlines
00500234.68mealsrestaurantThe Great Grill
00600222.40mealsrestaurantThe Great Grill
00700359.50entertainmenttheaterSilver Screen

Note that expense_type (what was bought) and vendor_type (the merchant category) are distinct — e.g. expense 001 is supplies purchased at a restaurant vendor.

Clarifying Questions to Ask

Scope the problem with the interviewer before designing. Strong candidates surface questions like:

  • What does "flag for review" mean operationally — is the engine advisory (returns violations for a human to review) or can a rule hard-block a transaction? Is there a single disposition per entity, or a full reason set?
  • Trust boundary on inputs — are the string-typed fields clean, or must amounts, categories, and vendor types be parsed and validated, with bad rows degrading gracefully rather than failing the batch?
  • Multi-tenancy from day one? Roughly how many companies, rules per company, and expenses per evaluation should the design target?
  • Who creates rules, and how often? Are rules static (deployed with code) or created at runtime via an API by managers — and must new rules ship without a client or schema change?
  • Field semantics — which rules key on vendor_type (merchant category) versus expense_type (spending category), given the two can diverge on the same row?
  • Currency — is every amount already in a single currency (USD here), or should the design anticipate mixed currencies / FX, tax/tip in caps, and per-diem windows?

Constraints & Assumptions

Anchor the design with explicit numbers and assumptions (confirm or adjust with the interviewer):

  • Scale: a single company may have 100+ rules for a manager/team to choose from; the API serves many companies (multi-tenant) concurrently.
  • Inputs: expenses arrive as Map<String, String> ; the amount field is amount_usd (single-currency, USD) — there is no per-row currency field in this data.
  • Contract stability: the return type is consumed by clients across many tenants and must be stable and backward-compatible — fields may be added, never renamed or removed.
  • Rule lifecycle: rules are data, not code — adding or creating a rule via API must not require a deploy.
  • Determinism: identical inputs must produce identical output (idempotent, deterministic ordering) for auditability and golden tests.

Part 1 — Per-expense rules

Base rules (must be supported)

  1. No restaurant expense over $75 .
  2. No airfare expenses.
  3. No entertainment expenses.
  4. No expense over $250 .

Against the sample data, the expected outcome is:

  • Expense 003 — a restaurant meal over $75 → should be reviewed.
  • Expense 004 — both airfare and over $250 → should be reviewed.
  • Expense 007 — entertainment → should be reviewed.

Function to implement

evaluateRules(rules: list<Rule>, expenses: list<Expense>) -> ReturnType
  • You define the rule types and their semantics (the four base rules above are passed as a list of four rules to the rules argument).
  • You define the return type . It will be used as a response from the expenses API, consumed by clients across many companies , so it must be stable and backward-compatible as rules evolve.

Design goals

  • Extensibility: support 100+ rules for a manager/team to choose from; allow adding new rules and rule creation via an API without breaking clients .
  • Evaluation semantics: specify
    • Priority / ordering of rules
    • Combinators (AND / OR / NOT)
    • Short-circuiting vs. exhaustive evaluation
    • Conflict resolution across rules
  • Explainability / audit: per-violation reason, rule metadata, timestamps, and who/what policy triggered the violation.
  • Production concerns: multi-tenant isolation, authorization, observability, idempotency, deterministic ordering, and resilience to partial failures.
  • Data models & parsing: define Expense , Trip , Rule , Policy , RuleResult , EvaluationSummary , and a strategy for parsing/validating amounts, categories, and vendor types from the string-typed inputs.

Part 2 — Aggregate (group-by) rules

The return value is now serving a large number of companies, and managers need to review not just individual expenses but trips that violate rules. Add support for trip-level rules such as:

  • (a) A trip's total expenses must not exceed $2000 .
  • (b) Total meal expenses per trip must not exceed $200 .

In the sample data, trip 002 violates both of these.

Requirements:

  • Extend the engine to evaluate both per-entity (expense) and aggregate (trip) rules in one pass , in addition to the Part 1 rules.
  • Describe your aggregation strategy, caching, and incremental updates .
  • Propose a backward-compatible return type that surfaces both expense-level and trip-level violations, including:
    • Entity type (expense / trip) and identifiers ( expense_id / trip_id )
    • Violated rule codes , severity , and human-readable messages
    • Machine-readable fields (e.g. observed_value , threshold , currency )
    • Pagination (cursor-based)

As in Part 1, discuss the return type before coding.

What a Strong Answer Covers

This is a checklist of the dimensions the interviewer is looking for — not the answers themselves:

  • Reads the input first — names the exact keys ( amount_usd , vendor_type , vendor_name ) and reasons about which field each rule keys on, given that vendor_type and expense_type can diverge on the same row, before writing any rule.
  • Return-type rationale — explicitly compares a structured-violation list against weaker shapes ( Map<id, bool> , string list) and justifies the choice in terms of backward compatibility across many tenants.
  • Declarative, data-driven rules — a stable rule_code , a condition tree with combinators (AND/OR/NOT), and rule creation via API with no deploy; clear evaluation semantics (priority/ordering, short-circuit within a rule vs. exhaustive across rules, conflict resolution).
  • Correct data models — Expense , Trip , Rule , Policy , RuleResult / Violation , EvaluationSummary , with a parsing/validation strategy for string inputs (fixed-point money, category normalization, graceful skip of bad rows).
  • One-pass evaluation of expense + trip rules, with the aggregation/caching/incremental-update story for scale.
  • Explainability & audit — per-violation reason, rule metadata, who/what policy fired it, and timestamps.
  • Production concerns — multi-tenant isolation, authorization/RBAC, observability, idempotency/determinism, partial-failure resilience, and cursor pagination.
  • Numeric correctness — money handled as fixed-point (not binary float); the candidate traces both the per-expense and per-trip outcomes against the sample data and arrives at a result consistent with the stated rules.

Follow-up Questions

Be ready for deeper probes after the main design:

  • How does the meal cap behave under multi-currency? If expenses arrive in mixed currencies, how do you normalize for a single threshold comparison, and what happens when an FX rate is unavailable at evaluation time?
  • A manager edits or deletes one expense on a closed trip — how do incremental aggregates and re-evaluation stay correct and idempotent without recomputing the whole trip?
  • What breaks first at 100× scale (millions of expenses, thousands of rules per evaluation) — latency, aggregation memory, the pagination contract, or the rule store — and how would you mitigate it?
  • A new rule type ships next quarter (e.g. per-day or per-month windows, or a per-diem). How does the return type and evaluation loop absorb it without a breaking change for existing tenant clients?

Product questions to clarify

Surface and reason about the open product questions, e.g.:

  • Policy scoping (company / team / user) and how 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 the return-type compatibility strategy over time.

Submit Your Answer to Earn 20XP

Sign in to leave a comment

Loading comments...

Browse More Questions

More System Design•More Rippling•More Software Engineer•Rippling Software Engineer•Rippling System Design•Software Engineer System Design

Your design canvas — auto-saved

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • AI Coding Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.