System Design: Delivery and Payment Services for Dasher Earnings
Context
You are designing two services:
-
Delivery service emits delivery lifecycle events.
-
Payment service consumes those events and computes dasher earnings and exposes query APIs.
Delivery events have fields {dasherId, deliveryId, timestamp, status}, where status ∈ {accepted, cancelled, fulfilled}.
Tasks
Design and justify the following:
-
APIs/interfaces between services (sync vs. async) and request/response schemas.
-
Payout rules (what gets paid on accepted/fulfilled, how cancellations affect pay) and how Payment calculates earnings for a dasher, including:
-
Totals over a time window.
-
Per-delivery breakdowns.
-
Time handling: representation of timestamp, time zones, ordering of events, and how to deal with late or out-of-order events.
-
Data modeling and storage (tables/indexes or in-memory structures) to support ingestion, deduplication, idempotency keys, querying by dasherId and time range, and efficient recalculation.
-
Reliability: error handling, retries, timeouts, circuit breakers—show where to add try/catch, logging, and metrics.
-
Consistency and reconciliation strategy (e.g., eventual consistency, exactly-once vs. at-least-once semantics, backfill jobs).
-
Service decoupling approaches (message bus, contracts, versioning, backward compatibility) and testing strategies.
-
What the Payment API should return for a typical request (e.g., total-to-date, time-bounded totals, per-delivery line items) and why.
If time permits, sketch key classes for both services and core methods for ingesting events and calculating payouts.