Katkat

Design in-memory delivery billing core APIs

RipplingSoftware Engineer · Onsite

Last updated

This problem tests your ability to design an efficient in-memory service for managing delivery billing, requiring careful consideration of concurrency, precision in monetary calculations, and optimized aggregation of billable events.

Problem Statement

Design an in-memory billing engine for a delivery platform that processes high-frequency delivery events. The system needs to calculate total billable amounts for drivers and companies in real-time.

Functional Requirements

  1. record_delivery(delivery_id, driver_id, company_id, amount_cents): Logs a completed delivery. If the delivery_id exists, update the amount.
  2. get_driver_total(driver_id): Returns the total earnings for a specific driver.
  3. get_company_bill(company_id): Returns the total amount owed by a specific company.

Non-Functional Requirements

  • The system must be thread-safe.
  • Operations should be optimized for sub-millisecond lookups.
  • Precision is critical; monetary values are stored in cents as integers to avoid floating-point issues.

Constraints

  • Number of drivers: 10^5
  • Number of companies: 10^3
  • Expected delivery events per second: 5,000
  • High concurrency is expected during peak hours.

Example

# Workflow example
engine = BillingEngine()
engine.record_delivery("d1", "dr_1", "c_1", 500)
engine.record_delivery("d2", "dr_1", "c_1", 300)

print(engine.get_driver_total("dr_1")) # Output: 800
print(engine.get_company_bill("c_1"))   # Output: 800

Edge Cases

  • Updating a delivery that has already been billed.
  • Handling empty IDs or zero-amount deliveries.

Hints

Hint 1

Use a hash map to track the current value of each delivery ID to handle updates correctly.

Hint 2

Maintain secondary hash maps or concurrent maps that store cumulative totals per driver and per company to avoid O(N) aggregation on every read.

Hint 3

Consider using fine-grained locking or atomic variables to ensure thread safety while minimizing contention during high-frequency writes.

Follow-up questions

  • How would you persist this data to a database while ensuring the in-memory state remains consistent with the disk?
  • If the billing logic changes (e.g., adding a platform fee percentage), how would you refactor your data structures to maintain performance?
  • How would you handle a scenario where 'get_company_bill' needs to support a date range filter?