system design

Low Level Design: ETL Service

What Is an ETL Service?

Extract, Transform, Load (ETL) is the classic pattern for moving data from operational systems into analytical stores. Unlike a streaming pipeline, ETL typically runs in scheduled batches: extract a snapshot or delta from the source, apply business-logic transformations, and load the result into a warehouse or data mart. The challenge is doing this reliably, repeatably, and without overloading the source system.

Data Model

-- ETL job definitions
CREATE TABLE etl_jobs (
  id             BIGINT PRIMARY KEY AUTO_INCREMENT,
  name           VARCHAR(255) NOT NULL UNIQUE,
  schedule_cron  VARCHAR(100) NOT NULL,    -- e.g. 0 2 * * *
  source_dsn     TEXT NOT NULL,            -- connection string (encrypted)
  source_query   TEXT NOT NULL,            -- parameterized SQL or API spec
  transform_ref  VARCHAR(255) NOT NULL,    -- class or script name
  target_table   VARCHAR(255) NOT NULL,
  load_strategy  ENUM('full', 'incremental', 'upsert') DEFAULT 'incremental',
  watermark_col  VARCHAR(100),             -- for incremental: updated_at
  last_watermark TIMESTAMP,
  enabled        BOOLEAN DEFAULT TRUE
);

-- Run history
CREATE TABLE etl_runs (
  id          BIGINT PRIMARY KEY AUTO_INCREMENT,
  job_id      BIGINT NOT NULL REFERENCES etl_jobs(id),
  run_start   TIMESTAMP NOT NULL,
  run_end     TIMESTAMP,
  rows_read   BIGINT DEFAULT 0,
  rows_loaded BIGINT DEFAULT 0,
  status      ENUM('running', 'success', 'failed', 'skipped') DEFAULT 'running',
  error_msg   TEXT,
  watermark_snapshot TIMESTAMP   -- value of watermark_col at run start
);

Core Workflow

  • The extract step begins when the scheduler triggers a job at the cron time. The extractor reads the last watermark from etl_jobs.last_watermark, issues a parameterized query (WHERE updated_at > :last_watermark), and streams results into local temp storage (disk-spilled if >100 MB). A snapshot of the current watermark is saved to etl_runs.watermark_snapshot before reading begins to avoid losing records written during the run.
  • In the transform step, records pass through a registered transform class. Typical operations: join with dimension tables (cached in memory for small dims, queried in batches for large ones), compute derived columns, normalize units, apply business rules. Output schema is validated against the target table DDL.
  • The load step bulk-loads rows into the warehouse. For full loads, swap a staging table into place atomically (RENAME TABLE or BigQuery table swap). For incremental/upsert loads, use the warehouse's native merge statement. On success, update etl_jobs.last_watermark to the snapshot value.

Failure Handling

  • On extract failure, log the error, leave last_watermark unchanged, and mark the run as failed. The next scheduled run re-extracts from the same watermark, with no data loss.
  • On transform failure, bad rows are written to a quarantine table with the original payload and error message. The job does not fail; a separate alert fires when the quarantine row count exceeds a threshold.
  • On load failure, staging data is preserved for manual inspection, and last_watermark is not advanced. Ops can replay the load step without re-extracting.
  • For idempotency, upsert loads are naturally idempotent. Full loads use a staging-table swap, which is atomic. Never advance the watermark until the load succeeds.

Scalability Considerations

  • For parallelism, large extracts split by a partition key (e.g., date range or shard ID) and run concurrently. The coordinator manages a semaphore to cap source DB connections.
  • For source protection, use read replicas for extraction. Rate-limit queries with a configurable max rows/second to avoid replication lag spikes.
  • For warehouse optimization, load into partitioned/clustered tables. Use columnar formats (Parquet, ORC) for staging files on object storage when the warehouse supports external table loads.
  • For the metadata store, a lightweight relational DB (PostgreSQL) tracks job state. At scale, add a Redis cache for scheduler hot-path reads to avoid thundering-herd on job-list queries.

See also: Databricks Interview Guide 2026: Spark Internals, Delta Lake, and Lakehouse Architecture

See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering

See also: LinkedIn Interview Guide 2026: Social Graph Engineering, Feed Ranking, and Professional Network Scale

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

1972 Soviet postage stamp commemorating the Mars 2 probe

worth a read

Mars For The Rest of Us — a weekly-or-more deep dive on the technical side of Mars exploration: rocket propulsion, microbiology, mission architecture, and everything in between. Written by Maciej Ceglowski.

Read it on Substack →
Scroll to Top