About Us Contact Us Write for Us Advertise
Home > System Design > Low-Level Design > Design Splitwise / Expense Sharing (Low-Level Design)
System Design › Low-Level Design

Design Splitwise / Expense Sharing (Low-Level Design)

Design an expense-sharing app like Splitwise in an LLD interview: split strategies (equal/exact/percentage), the who-owes-whom balance model, and the debt-simplification bonus. Classes, UML, and design decisions.

Shiv Pandey
Shiv Pandey
Oct 27, 2026 | 64 views
Design Splitwise / Expense Sharing (Low-Level Design)

🟠 Low-Level Design · Case Study · Senior

"Design Splitwise" (an expense-sharing app) is a favourite because it has a clean object model and two interesting sub-problems: supporting different ways to split an expense, and tracking who owes whom so debts can be simplified. It's a great showcase for the Strategy pattern plus a little graph thinking.

The approach in one line: an Expense is paid by someone and split among people via a pluggable split Strategy (equal / exact / percentage); the system maintains a balance sheet of pairwise debts, and can simplify them to minimise the number of settlements.

Step 1 — Requirements

  • Functional: users and groups; add an expense (who paid, total, participants) split equally, by exact amounts, or by percentage; show each person's balance (owes / is owed); settle up; optionally simplify debts.
  • Non-functional: balances always add up to zero, splitting is extensible, correct to the cent.

Step 2 — The classes

  • User, Group (a set of users).
  • Expense — amount, who paid, and a list of Splits (participant → share).
  • SplitStrategy (interface) → EqualSplit, ExactSplit, PercentSplit — computes each participant's share.
  • BalanceSheet / ExpenseManager — tracks pairwise balances (who → whom → amount) and updates them on each expense.

Step 3 — Splitting = Strategy

🟠 The different split types are interchangeable algorithms — textbook Strategy:

interface SplitStrategy { Map<User,Double> split(double amount, List<User> users, double[] values); }

class EqualSplit implements SplitStrategy {
    public Map<User,Double> split(double amt, List<User> users, double[] v){
        double share = amt / users.size();          // everyone equal
        // return each user → share
    }
}
class PercentSplit implements SplitStrategy { /* share = amt * pct[i]/100 */ }
class ExactSplit   implements SplitStrategy { /* share = given exact values */ }

Adding a new split type (e.g. "by shares") is a new class — no changes elsewhere. Each strategy also validates (exact splits must sum to the total; percentages to 100).

Step 4 — Tracking balances

🔴 The core data structure: a balance map — balances[A][B] = amount A owes B (negative means B owes A). When Alice pays $30 split equally among Alice, Bob, Carol, each owes $10; Bob and Carol each owe Alice $10, so you update balances[Bob][Alice] += 10 and balances[Carol][Alice] += 10.

Alice Bob Carol owes $10 owes $10 Alice paid $30, split 3 ways → Alice is owed $20

Step 5 — The senior bonus: simplify debts

🔴 A classic follow-up: minimise the number of transactions to settle up. If Bob owes Alice $10 and Carol owes Bob $10, don't do two payments — have Carol pay Alice directly. This is a debt-simplification problem: compute each person's net balance (total owed − total owing), then match the biggest debtor to the biggest creditor repeatedly (a greedy min-cash-flow). Mentioning "reduce to net balances, then greedily settle max debtor↔max creditor" is a standout senior answer.

Step 6 — Design notes

🟠 Keep money in integer cents (or BigDecimal) to avoid floating-point errors — a real Splitwise concern. Validate splits sum to the total. Groups are just a convenience over the same balance engine. Optionally record an Expense history for an audit trail.

The interview-ready walkthrough

"An Expense has a payer and splits computed by a pluggable SplitStrategy — Equal, Exact, Percentage — each validating its input; new split types are new classes. I track a balance map of who-owes-whom, updated per expense, and provide settle-up. As a bonus I'd simplify debts by reducing to net balances and greedily matching the biggest debtor to the biggest creditor to minimise transactions. I'd use integer cents / BigDecimal to avoid rounding errors." That hits Strategy, the balance model, and the debt-simplification bonus."

What to read next

← Design BookMyShow · Design an LRU cache →

Related Articles

Design a Food Delivery App (Low-Level Design)
System Design › Low-Level Design

Design a Food Delivery App (Low-Level Design)

Design a Meeting Scheduler (Low-Level Design)
System Design › Low-Level Design

Design a Meeting Scheduler (Low-Level Design)

Design Snake and Ladder (Low-Level Design)
System Design › Low-Level Design

Design Snake and Ladder (Low-Level Design)

Design Chess (Low-Level Design)
System Design › Low-Level Design

Design Chess (Low-Level Design)