The API Drip Feed

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

Design the pipeline that syncs tasks, users, and projects from a third-party project management SaaS API into our analytics warehouse, where one tracked dashboard reads the task data.

The API gives you 100 records at a time. You need millions.

Business requirements

Worked solution and explanation

What this problem is really testing

This is change capture by polling a hostile API, dressed up as a project-management sync. Three stressors hit the warehouse at once: small rate-limited pages that burst unevenly, one dashboard that needs freshness the rest of the tables do not, and field names that drift every few weeks. Anyone can draw a straight line from the API to the warehouse. The separating move is refusing to let any one stressor reach the tables. Skip it and you drop records on a burst, miss the dashboard's hour, or load a renamed field as a column of nulls that nobody notices for a week.

Walk the requirements

Step 1: Buffer the API before anything reads it

A loader that reads the API directly must keep up with a burst or drop pages when it backs off on a 429. A queue (ingest_buffer) decouples fetch rate from load rate: the fetcher writes pages as they arrive, the loaders drain at their own pace, and throttling stalls a consumer without losing what is already buffered.

Step 2: Split the load into two cadences

The rate limit cannot cover pulling every table fresh each hour, and a daily-only design misses the dashboard's window. So hourly_task_loader pulls only task updates and daily_batch_loader refreshes the rest. An orchestrator paces both against the request budget, and cursor_state_store holds each loader's high-water mark so a run asks only for what changed.

Step 3: Validate the schema ahead of the warehouse

A vendor rename is silent. If loaders write what they receive, the old column fills with nulls and the table is quietly wrong. schema_validation_gate checks the shape of every batch from both loaders, passes clean ones to analytics_warehouse, and routes a mismatch to team_alerting, so the team fixes the mapping once instead of finding it in a broken report.

The shape that fits

A queue absorbs the bursty API. Two loaders off it give an hourly task path and a daily path for everything else. Every batch passes `schema_validation_gate` before the warehouse, and a mismatch goes to `team_alerting`.
  • vendor_api (source, API)
  • ingest_buffer (queue, Kafka)
  • orchestrator (transform, Airflow)
  • cursor_state_store (storage, PostgreSQL)
  • hourly_task_loader (transform, Spark); freshness: < 1h
  • daily_batch_loader (transform, dbt); freshness: < 24h
  • schema_validation_gate (quality gate, Great Expectations)
  • analytics_warehouse (storage)
  • team_alerting (consumer)
  • tracked_dashboard (consumer)
  • vendor_api -> ingest_buffer
  • ingest_buffer -> hourly_task_loader
  • ingest_buffer -> daily_batch_loader
  • orchestrator -> hourly_task_loader
  • orchestrator -> daily_batch_loader
  • cursor_state_store -> hourly_task_loader
  • cursor_state_store -> daily_batch_loader
  • hourly_task_loader -> schema_validation_gate
  • daily_batch_loader -> schema_validation_gate
  • schema_validation_gate -> analytics_warehouse
  • schema_validation_gate -> team_alerting
  • analytics_warehouse -> tracked_dashboard
  • Source and buffer: vendor_api, ingest_buffer
  • Orchestration and state: orchestrator, cursor_state_store
  • Tiered loaders: hourly_task_loader, daily_batch_loader
  • Validate and land: schema_validation_gate, analytics_warehouse
  • Consumers: team_alerting, tracked_dashboard

Common follow-up questions