PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep
|Home/System Design/Rippling

Design a delivery cost system

Last updated: Jun 21, 2026

Quick Overview

A Rippling software-engineer system-design screen: build an object-oriented, in-memory delivery cost system that registers drivers with hourly rates, records deliveries, and reports total cost, paid/unpaid amounts via an idempotent payUpTo cutoff, and the max number of drivers simultaneously delivering in the last 24 hours. It tests time-interval modeling, exact monetary arithmetic, sweep-line concurrency, idempotency, time-zone handling, and thread-safe dashboard reads.

  • medium
  • Rippling
  • System Design
  • Software Engineer

Design a delivery cost system

Company: Rippling

Role: Software Engineer

Category: System Design

Difficulty: medium

Interview Round: Technical Screen

##### Question Design an object-oriented, in-memory **Delivery Cost System** for a food-delivery company. Drivers register with an hourly rate, deliveries are recorded as they complete, and the system reports cost and payment metrics for a live dashboard. Implement the following: 1. **`registerDriver(driverId, hourlyRate)`** — Add or update (upsert) a driver and their hourly rate. Drivers may have different rates. Decide whether a rate change should affect already-recorded deliveries. 2. **`recordDelivery(driverId, startTime, endTime)`** — Record one completed delivery. Cost accrues as `hourlyRate(driverId) x duration`. Deliveries are recorded immediately after completion and last no more than 3 hours. A single driver may have overlapping deliveries, and each is paid independently. Define interval semantics (inclusive/exclusive endpoints), how partial hours are prorated, and the time representation (require at least one-second precision). 3. **`getTotalCost()`** — Return the aggregated cost of all recorded deliveries across all drivers. This drives a live dashboard, so it should be cheap to call. 4. **`payUpTo(timestamp)`** — Mark all accrued cost up to the given timestamp as paid. A delivery that straddles the timestamp should have only the portion up to the timestamp counted as paid. Repeated or earlier calls must be idempotent. 5. **`getTotalUnpaid()`** — Return the remaining unpaid amount. 6. **`maxSimultaneousDriversInPast24Hours()`** — Return the maximum number of drivers that were simultaneously on a delivery at any instant within the last 24 hours. Discuss your class design, core data structures, method signatures, numeric precision (avoiding floating-point money errors), rounding, time-zone handling, thread-safety for a concurrent dashboard, idempotency, and the time/space complexity of each operation.

Quick Answer: A Rippling software-engineer system-design screen: build an object-oriented, in-memory delivery cost system that registers drivers with hourly rates, records deliveries, and reports total cost, paid/unpaid amounts via an idempotent payUpTo cutoff, and the max number of drivers simultaneously delivering in the last 24 hours. It tests time-interval modeling, exact monetary arithmetic, sweep-line concurrency, idempotency, time-zone handling, and thread-safe dashboard reads.

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)
Rippling logo
Rippling
Jul 31, 2025, 12:00 AM
Software Engineer
Technical Screen
System Design
94
0

Design an object-oriented, in-memory Delivery Cost System for a food-delivery company.

Drivers register with an hourly rate, completed deliveries are recorded as they finish, and the system reports cost and payment metrics for a live dashboard. Implement the API in the Parts below, then walk through your design decisions.

Clarifying Questions to Ask

A strong candidate scopes the whole problem before coding. Reasonable questions to raise with the interviewer:

  • What are the interval semantics for a delivery — are the endpoints inclusive or exclusive, and how should a delivery that ends exactly when another begins be treated?
  • Should a rate change via registerDriver reprice deliveries that were already recorded , or apply only to future ones?
  • What is the read:write ratio — how hot are the dashboard reads relative to recordDelivery ?
  • For the concurrency metric, are we counting distinct drivers simultaneously active, or distinct deliveries (these differ when one driver overlaps themselves)?
  • What money precision and rounding policy is expected, and do the dashboard's paid/unpaid/total figures need to reconcile exactly?
  • Are input timestamps guaranteed in UTC , or can they arrive zoned / as local wall-clock time?

Constraints & Assumptions

  • Everything lives in memory — no database is required for the core design (though you may discuss persistence as an extension).
  • Drivers may have different hourly rates , and a rate can be updated over time.
  • A single driver may run overlapping deliveries , and each delivery is paid independently.
  • Each delivery lasts no more than 3 hours and is recorded immediately after it completes.
  • Time must support at least one-second precision .
  • The dashboard reads ( getTotalCost , getTotalUnpaid ) and the write path ( recordDelivery ) may run concurrently .

Part 1 — registerDriver(driverId, hourlyRate)

Add or update (upsert) a driver and their hourly rate. Decide whether changing a rate should affect already-recorded deliveries, and justify your choice.

What This Part Should Cover

  • Upsert correctness — clean driverId -> rate storage with validation (e.g. non-negative rate).
  • The rate-change decision — a justified choice (snapshot the rate per delivery vs. look it up live at read time) stated explicitly as an assumption, with the payroll rationale.

Part 2 — recordDelivery(driverId, startTime, endTime)

Record one completed delivery. Cost accrues as hourlyRate(driverId) × duration. When defining this method, specify:

  • Interval semantics — are endpoints inclusive or exclusive (e.g. [start, end) )?
  • Proration — how partial hours are handled.
  • Time representation — the type/units used to store an instant (one-second precision or finer).

What This Part Should Cover

  • Interval semantics — an unambiguous, explicitly-stated convention (half-open [start, end) is conventional) and why it removes boundary ambiguity.
  • Exact proration — linear proration of partial hours via an integer/decimal accumulator, with the lossy division deferred to read time.
  • Validation — rejecting unknown drivers, non-positive durations, and over-cap deliveries; handling a driver's overlapping deliveries as independent records.

Part 3 — getTotalCost()

Return the aggregated cost of all recorded deliveries across all drivers. This powers a live dashboard, so it should be cheap to call.

What This Part Should Cover

  • Constant-time read — a running aggregate updated incrementally on write, not an O(N) scan.
  • Rounding at the boundary — the exact internal accumulator is converted to dollars and rounded only here, with the rounding policy named.

Part 4 — payUpTo(timestamp)

Mark all accrued cost up to timestamp as paid. A delivery that straddles the timestamp counts only the portion up to the timestamp as paid. Repeated calls, or calls with an earlier timestamp, must be idempotent.

What This Part Should Cover

  • Cutoff model — a single monotonic paid-through instant rather than per-row mutation, with the straddle split derived from interval math.
  • Idempotency — a max -style update that makes repeated or earlier calls no-ops, and how that property survives concurrent callers.

Part 5 — getTotalUnpaid()

Return the remaining unpaid amount.

What This Part Should Cover

  • Correct per-delivery overlap — the unpaid slice max⁡(0, e−max⁡(s,P))\max(0,\ e - \max(s, P))max(0, e−max(s,P)) at the snapshot rate, summed exactly.
  • The O(N) → O(1) trade — recognizing the naive scan and offering a precomputed-accrual alternative that shifts work onto payUpTo .

Part 6 — maxSimultaneousDriversInPast24Hours()

Return the maximum number of distinct drivers simultaneously on a delivery at any instant within the last 24 hours.

What This Part Should Cover

  • Correct sweep line — windowing/clipping to the last 24 h and a running-max over sorted start/end events.
  • Distinct-driver handling — a per-driver interval union so a single driver overlapping themselves contributes at most one unit, distinguishing this from a max-simultaneous- deliveries reading.
  • Boundary tie-breaking — ordering -1 before +1 at equal timestamps to honor half-open semantics.

What a Strong Answer Covers

These dimensions span all Parts; the interviewer is looking for them across the whole design, not for the answers themselves:

  • Class design & data structures — clean OO types (driver registry, delivery log, a service facade) and the exposed method signatures .
  • Time model consistency — UTC epoch storage, one explicit interval convention used everywhere, and time-zone handling at the API boundary.
  • Money representation consistency — one exact (non-float) numeric scheme, an explicit rounding policy applied only at output, and paid/unpaid/total reconciliation.
  • Performance — O(1) dashboard reads via running aggregates, and the time/space complexity of every operation.
  • Thread-safety — how concurrent reads and writes stay correct on the dashboard's hot path, including any cross-read reconciliation caveat.

Follow-up Questions

Be ready for deeper probes after the main design:

  • How does this change at 100× scale — say 10810^8108 historical deliveries — and which operation breaks first?
  • If getTotalUnpaid and payUpTo become hot, can you make the unpaid read O(1) , and what does that cost shift onto payUpTo ?
  • How would you add a persistence layer, and which indexes would you create to keep the windowed concurrency and payment-cutoff queries fast?
  • How would you support a driver's rate changing partway through a single delivery?

Solution

Show

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
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
  • Compare Platforms
  • Discord Community

Support

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

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.