The Register Never Sleeps

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

POS terminals in 600 stores write each day's sales to S3 as one file per store after close, and the Snowflake warehouse loads those files overnight. Design a pipeline that lands each sale in the warehouse within minutes instead.

Every swipe lands in the warehouse. The table has to stay current without breaking.

Business requirements

Worked solution and explanation

What this really is

This is a change-data problem wearing a retail costume. A void isn't a new sale: it restates an old one. A silent register isn't missing data: it is the signal. Swapping the end-of-day batch for continuous ingestion is the easy half everyone reaches for. The trap is treating the void as just another row and trusting someone to notice a dark store. Get the first wrong and fact_sales carries both 'completed' and 'voided' for one transaction id, so totals diverge from the register tape. Get the second wrong and ops learns a store died at noon only when nightly numbers come in low.


Walk the requirements

Step 1: Land each sale within minutes

Once terminals upload a small file every minute or two, an S3 event notification triggers continuous_ingest to load each file into staging_table on arrival, and ops_dashboard reads the warehouse. There is no end-of-day wait. When a store reconnects after an outage and dumps a backlog, the loader absorbs it one file at a time.

Step 2: Resolve voids against the original by id

staging_table holds what landed, replays included. fact_sales_merge runs a MERGE keyed on transaction id: a new sale inserts and a replayed one rewrites the same row. A void or price correction arrives as a new event referencing the original id, and it updates that row's status and net amount instead of appending. Appending the void is the version where duplicates pile up and totals drift.

Step 3: Alert on silence during business hours

heartbeat_monitor tracks per-store arrival. When a store goes quiet past its expected tolerance during opening hours, it fires to ops_alerts with the store id and last-seen time. Catching the gap at end of day is the failure this replaces.


The shape that fits

`continuous_ingest` loads each S3 file into `staging_table` on arrival. A `MERGE` keyed on transaction id writes `fact_sales`, absorbing replays and resolving voids and corrections in place. `heartbeat_monitor` alerts ops to silent stores during business hours.
  • pos_terminals (source, API)
  • s3_staging (storage, S3)
  • continuous_ingest (transform, SQL); freshness: < 1min
  • staging_table (storage, Snowflake)
  • fact_sales_merge (transform, dbt); idempotency: upsert
  • fact_sales (storage, Snowflake)
  • heartbeat_monitor (quality gate, custom); alerting: Store silent past expected business-hours tolerance
  • ops_dashboard (consumer, dashboard)
  • ops_alerts (consumer, alerting)
  • pos_terminals -> s3_staging
  • s3_staging -> continuous_ingest
  • continuous_ingest -> staging_table
  • staging_table -> fact_sales_merge
  • fact_sales_merge -> fact_sales
  • fact_sales -> heartbeat_monitor
  • fact_sales -> ops_dashboard
  • heartbeat_monitor -> ops_alerts

Common follow-up questions