Every Scan, Every Parcel, Every Pin Code

A medium Pipeline Design interview practice problem on DataDriven. Design the pipeline on the canvas: sources, transforms, storage and checks, then get feedback on it.

Domain
Pipeline Design
Difficulty
medium
Seniority
L5

Problem

How would you keep shipment state accurate when tracking scans from warehouses, vehicles and delivery points across 18,000 pin codes in India arrive out of order, so a delivery scan can land before the origin hub's departure scan? The ops team also has to catch parcels moving in the wrong direction.

Out for delivery. Delivered. Except the events arrived backwards.

Business requirements

Worked solution and explanation

Why this problem exists in real interviews

Out-of-order tracking scans are a stateful-streaming problem in disguise: customers want the latest state in minutes, ops wants the absence of state (stuck parcels), and routing wants a lookup fast enough not to slow scanning. The trap is treating each scan as it arrives without a per-parcel state machine keyed by AWB. Get it wrong and a delivery scan that lands before the origin scan flashes 'delivered' on a parcel that never shipped.

The first reach is a stream that upserts each scan into a tracking table by parcel id, keeping the latest by event-time. But if the delivery scan arrives first the customer page briefly contradicts itself; ops queries 'not moving' on a slow batch and learns of stuck parcels hours after customers do; and routing reads pin-code reference from the OLTP on every scan until it buckles.


Walk the requirements

Step 1: Stream into a per-parcel state machine that respects event-time

Scan events flow through a queue into a stream processor keyed by AWB. For each parcel the processor holds an event-time-ordered list of scans and emits the resulting state to the tracking store, so an out-of-order delivery scan arriving before the origin scan doesn't flash 'delivered'. Without stateful streaming the customer view is whichever scan landed last, not the parcel's real progress.

Step 2: Stuck-shipment detection as a watermark timer on the stream

The same per-parcel state arms a watermark-driven timer that fires when no scan arrives inside the operational window, emitting a 'stuck' exception that reaches ops as an alert. Because it's event-time driven, a delayed batch of scans doesn't trigger false alerts. A periodic batch query for 'no recent scan' lags by the batch interval and floods the store on every load.

Step 3: Routing reference in a cache the stream reads, not the OLTP

Routing lookups run on every scan at peak, so the stream reads pin-code routing from an in-memory cache with a tens-of-milliseconds budget instead of the OLTP. The same lookup tells the stream when a scan lands off the parcel's expected route, and that misroute goes to ops through the same exception path as a stuck parcel.


The shape that fits

Scans buffer in `scan_events_raw`; `tracking_stream` keeps per-parcel state in event-time order, reads `pin_code_routing` from a cache, and writes `shipment_state` for customers and `delivery_exceptions` for ops.
  • scanners (source, API)
  • scan_events_raw (queue, Kafka)
  • tracking_stream (transform, Flink)
  • pin_code_routing (storage, Redis)
  • shipment_state (storage, PostgreSQL)
  • delivery_exceptions (storage, PostgreSQL)
  • customer_tracking (consumer, API)
  • ops_alerting (consumer, Grafana)
  • scanners -> scan_events_raw
  • scan_events_raw -> tracking_stream
  • pin_code_routing -> tracking_stream
  • tracking_stream -> shipment_state
  • tracking_stream -> delivery_exceptions
  • shipment_state -> customer_tracking
  • delivery_exceptions -> ops_alerting
  • Ingest: scanners, scan_events_raw
  • Stream + lookup: tracking_stream, pin_code_routing
  • Serving: shipment_state, delivery_exceptions, customer_tracking, ops_alerting

Common follow-up questions