Five Years of Cron Jobs

A hard 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
hard
Seniority
L6

Problem

Our data platform grew over five years into a mix of on-premises cron jobs and pipelines triggered by upstream system callbacks, and it all has to move to one cloud-native orchestration platform while the legacy runs stay live until each pipeline proves out. Design the migration architecture and the run logging and observability schema behind it.

Half the jobs run on cron. Half run on events. All of it has to move.

Business requirements

Worked solution and explanation

What this really is

This is a strangler-fig migration dressed up as a logging question. Anyone can draw Airflow and an object store. What separates candidates is treating cutover as an evidence-gated decision: every pipeline dual-runs, a parity check compares cloud against on-prem, and on-prem stays authoritative until the diff holds. Skip that and three things break. Analytics becomes your test suite, the third of pipelines that fire on callbacks silently start waiting for a cron tick, and the first audit question gets answered with grep.

Walk the requirements

Step 1: Dual-run every migrating pipeline

Cloud and legacy both run for the agreed window, each writing to its own output. The old path never stops, so analytics sees no freshness gap and no missed run.

Step 2: Keep event triggers as event triggers

Route upstream callbacks onto a queue the orchestrator listens to, so each run starts when the upstream is ready. Fold them into a schedule and you add a polling delay nobody signed up for. Scheduled and event-triggered runs stay separate paths.

Step 3: Diff the outputs and let on-prem win

The parity gate compares cloud and legacy outputs run by run. Out of tolerance means legacy stays authoritative. Within tolerance for the full window flips the pointer in migration_state. No manual sign-off.

Step 4: Write a structured record for every run

Every run writes a row to pipeline_run_log: run id, pipeline, trigger type, start, end, status, input and output pointers, error context. Task detail goes to task_execution_log. The log lands in object storage as a queryable table kept for the regulatory window.

The reference design

Callbacks and schedules drive one Airflow tier. Cloud output meets legacy output at the parity gate, so analytics only sees cloud results once they match and legacy stays authoritative otherwise. Every run lands in a queryable run log on durable storage.
  • upstream callbacks (queue, Kafka)
  • legacy outputs (source, CDC)
  • orchestrator (transform, Airflow)
  • scheduled runs (transform, Spark)
  • event triggered runs (transform, Spark)
  • cloud outputs (storage, Iceberg)
  • parity gate (quality gate, Great Expectations)
  • run log (storage, Iceberg)
  • analytics dashboard (consumer, Metabase)
  • audit dashboard (consumer, Metabase)
  • upstream callbacks -> orchestrator
  • orchestrator -> scheduled runs
  • orchestrator -> event triggered runs
  • scheduled runs -> cloud outputs
  • event triggered runs -> cloud outputs
  • scheduled runs -> run log
  • event triggered runs -> run log
  • legacy outputs -> parity gate
  • cloud outputs -> parity gate
  • parity gate -> analytics dashboard
  • run log -> audit dashboard
  • Triggers + legacy: upstream callbacks, legacy outputs, orchestrator
  • Runs: scheduled runs, event triggered runs
  • Outputs + parity: cloud outputs, parity gate, run log
  • Consumers: analytics dashboard, audit dashboard
Port and switch
Pipelines move one at a time and analytics is repointed after a spot check. Discrepancies surface a week later, reported by the analytics team. Rollback means re-enabling cron by hand.
Dual-run with parity gate
Both systems run side by side, a daily diff decides, and the flip is config. Rollback means flipping the pointer back, and the diff history explains why.

Common follow-up questions