Skip to content

Splitwise#

Problem statement (interviewer prompt)

Design Splitwise: groups of friends log shared expenses (equal / unequal / by share / by percentage), and the app shows who-owes-whom balances. Add a "simplify debts" feature that reduces the number of payments in a group to settle up.

flowchart LR
  U([User])
  EXP[Expense Service]
  GRP[Group / Friends]
  BAL[Balance Service]
  SETT[Settlement / Simplify]
  U --> EXP --> BAL
  GRP --- EXP
  BAL --> SETT

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class U client;
    class EXP,GRP,BAL,SETT service;
flowchart TB
  subgraph Apps
    APP
    WEB
  end

  subgraph Edge
    CDN
    GW
  end

  subgraph Domain
    USR[Users]
    GRP[Groups + memberships]
    EXP[Expense Service]
    SPLIT[Splitter<br/>equal / unequal / shares / percentage / exact]
    CAT[Categories]
    CURR[Currency / FX]
    REC([Receipt OCR])
    OBJ[Image store]
  end

  subgraph Ledger
    JE[(Journal entries<br/>per-pair balance)]
    BAL[Pair balance materialized]
    GROUP_BAL[Group balance]
    SETTLE[Simplify-debts algorithm]
    PAYREC[Settle Up records]
  end

  subgraph Notif
    PUSH
    EMAIL
    REMIND[Reminders]
  end

  subgraph Sync
    OFF[Offline support]
    CONF[Conflict resolution<br/>last-writer-wins / per-expense version]
  end

  subgraph Integration
    UPI_LINK[UPI / payment link out]
    EXPORT[CSV / Excel export]
  end

  Apps --> CDN --> GW --> Domain
  Domain --> Ledger
  Ledger --> Notif
  Integration --- Ledger

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class USR,GRP,EXP,SPLIT,CAT,CURR,BAL,GROUP_BAL,SETTLE,PAYREC,REMIND,OFF,CONF,UPI_LINK,EXPORT service;
    class OBJ,JE datastore;
    class REC compute;

Data model#

  • One expense → many participants with share_amount.
  • Each expense generates symmetric journal entries between payer and others.
  • Per-pair balance = sum of (i,j) - sum of (j,i).
  • Group balance = sum of pair balances within group.

Simplify debts#

  • Net all pair balances within a group.
  • Reduce to minimum number of payments: classic flow / greedy net-positions algorithm.

Multi-currency#

  • Each expense in original currency; store exchange rate snapshot at create.
  • Recompute display in user's preferred currency.

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
HLD CDN edge caching for static assets cdn

Quick reference#

Functional#

  • Add expense (payer + participants + split rule).
  • Groups, friends, categories.
  • Pair / group balances.
  • Settle up (record payments, simplify debts).
  • Receipts, comments, reminders.
  • Multi-currency.

Non-functional#

  • Eventual consistency OK; offline-first.
  • p99 add expense < 500 ms.
  • Reliable balance correctness.

Capacity#

  • ~50M users, hundreds of millions of expenses.
  • Per-user data is small (KB-MB).

Schema#

  • users(id, name, email, default_ccy)
  • groups(id, name, members[])
  • expenses(id, group_id, payer_id, amount, ccy, ts, split_method, shares[])
  • journal(pair_a, pair_b, amount_ccy, expense_id)

Trade-offs#

  • Materialized pair balance vs on-the-fly sum: materialize for fast reads; recompute occasionally.
  • Currency conversion uses snapshot at create, not display time.
  • Concurrent edits: per-expense version + LWW; for groups, CRDT-ish merge.

Refs#

  • Splitwise engineering posts.
  • "Building Splitwise" blog by founders.
  • ByteByteGo "Design Splitwise".

FAQ#

How does Splitwise calculate who owes whom?#

Splitwise stores each expense with payer and participants, generates journal entries between pairs, and materializes pair balances to show net amounts owed within a group.

What is the debt simplification algorithm in Splitwise?#

Debt simplification nets all pair balances within a group and uses a greedy or flow-based algorithm to reduce the number of payments required to settle everyone up.

How does Splitwise handle multiple currencies?#

Each expense stores its original currency plus an exchange-rate snapshot at creation time. Balances are computed in the original currency and displayed in the user's preferred currency.

How does Splitwise work offline?#

The app supports offline-first edits with per-expense versioning and last-writer-wins conflict resolution, syncing changes when connectivity returns.

Why use a journal-style ledger for expense tracking?#

A journal lets every expense produce symmetric debit and credit entries between members, which makes balances reconstructible and auditable.

What are the main tradeoffs when designing Splitwise?#

Key tradeoffs include materializing pair balances vs computing on the fly, snapshot vs live currency conversion, and how aggressively to merge concurrent group edits.

Video walkthrough

Design Splitwise: HLD + LLD Complete Walkthrough : via System Design Walkthrough