System design template

Data warehouse ETL architecture.

Land the raw data first and transform it later, because the transformation you want in six months is not the one you would write today.

Download for macOS
v0.1.33 · .dmg · Apple Silicon & Intel
Signed & notarized by Apple · opens without a Gatekeeper warning
sha256 698955a0187bc039f4c74f5d05a9f10fbb27376a45788a0a241d1326b73873c7
Download for Windows instead
$curl -fsSL https://lucidtrain.com/install.sh | sh
Data warehouse ETL pipeline architecture. 11 components across 5 tiers.
Data warehouse ETL pipeline architecture. Rendered by the same ELK layout engine the app runs: the agent emits components, tiers and edges, and the engine places them, so the boxes cannot overlap.

The components

Every row below is read from the graph that produced the diagram above, so the two cannot disagree.

ComponentTierWhy it is there
Source databasesClientSupporting component
SaaS APIsExternalSupporting component
CDC connectorApplicationReads the write-ahead log, not a nightly SELECT
Ingest jobsApplicationSupporting component
OrchestratorApplicationDAGs with real dependencies and retries
Transform layerApplicationSQL models, version controlled and tested
Data qualityApplicationFails the DAG, does not just log a warning
Data lakeDataRaw, immutable, replayable
KafkaDataSupporting component
WarehouseDataSupporting component
BI & dashboardsInfrastructureSupporting component

Design decisions worth arguing about

A diagram shows what was chosen. It does not show what it cost, and that is usually the part that matters in a review or an interview.

Extract, load, then transform

Transforming before landing means the only data you keep is what your current logic produced, so a bug or a changed definition requires re-extracting from sources that may no longer have the history. Landing raw first makes every transform replayable. It costs storage for data you may never query, which is cheap, and it is the decision people most regret not making.

Change data capture rather than nightly full extracts

Reading the write-ahead log gives near-real-time changes and puts almost no load on the source database, where a nightly full table scan does the opposite on both counts. The cost is operational: CDC is more moving parts, it is sensitive to schema changes, and a connector that falls behind is not obvious until someone notices yesterday's numbers.

Transforms as version-controlled SQL

Transformation logic buried in a scheduler's UI or in notebooks cannot be reviewed, tested or rolled back. Expressing it as SQL models in a repository makes it ordinary software. The cost is that analysts have to work through code review, which is a genuine friction and is also the entire reason the numbers become trustworthy.

Quality checks that fail the run, not that log a warning

A warning nobody reads is not a check. Failing the DAG means bad data does not reach the dashboards, at the cost of dashboards being stale instead of wrong. Stale is recoverable and visible; wrong is neither, and a decision made on wrong numbers is not undone by fixing them later.

How it changes with scale

Warehouse cost is driven by query patterns rather than by storage, so partitioning and clustering to match how people actually query is where the money is. Pipeline runtime grows with the number of models more than with data volume, which makes DAG structure and incremental models the lever once the model count gets large.

Where it breaks first

Silent schema drift. A source adds or renames a column, the pipeline keeps running because nothing errors, and a downstream metric quietly changes meaning. This surfaces weeks later as a disagreement between two dashboards, which is why schema assertions belong in the pipeline rather than in a runbook.

Draw this yourself

Open the Diagram tab and describe the system. The agent emits a semantic graph rather than coordinates, so you can edit the components and the layout re-solves instead of drifting.

shell
$ Diagram a data warehouse ETL pipeline: change data capture from source databases and API ingestion from SaaS tools, a raw immutable data lake, an orchestrator running transform DAGs, data quality checks that fail the run, a warehouse and BI dashboards.

When the shape is right, Implement in code turns the canvas into a markdown specification, every component, every relationship and the notes, and starts a real turn in the Code tab with it.

FAQ

Questions about this design

Do you need a data lake as well as a warehouse?

The lake is the replay buffer: cheap, immutable, everything. The warehouse is the query layer: expensive, modelled, fast. Skipping the lake works until the first time you need to rebuild a model from history.

How fresh should the warehouse be?

As stale as the decisions allow. Most business questions are answered fine by hourly or daily data, and pushing toward streaming multiplies cost and complexity for a freshness nobody acts on.

Should transforms run in the warehouse or before it?

In the warehouse, in almost every case. Modern warehouses are good at this and it keeps the logic in SQL where analysts can read it. Pre-warehouse transformation is for reshaping that SQL genuinely cannot express.

Who owns data quality?

Whoever owns the source, which is the unpopular answer. Quality checks in the pipeline catch problems; only the producing team can fix the cause, and a pipeline that silently compensates for bad sources hides the problem indefinitely.

More templates