Skip to content

The Ultimate Guide to ELT

June 2026

A practical guide to ELT: architecture, raw landing, dbt, batch versus CDC, warehouse fit, and the operating model behind modern analytics stacks.

Start Here: What ELT Actually Is

ELT stands for extract, load, transform. Data is extracted from a source, loaded into a warehouse or lakehouse in a raw or lightly typed form, and then transformed inside the destination using warehouse-native compute, usually with SQL and tools such as dbt.

The order matters. In classic ETL, the transformation engine sits before the destination. In ELT, the warehouse itself becomes the transformation engine. That changes the economics, the tooling, and the working style. Engineers and analysts can model directly in the destination, keep raw history close, and iterate on semantics without re-extracting the full source every time.

A concrete example helps. A PostgreSQL application database feeds a Snowflake warehouse. In ELT, you land raw tables such as RAW.orders and RAW.customers first, then build staging and mart logic on top in dbt. In ETL, you would more likely reshape the data before it ever reached Snowflake. Both can work. ELT became common because cloud warehouses made the post-load path much cheaper and easier to operate.

  • ELT is strongest when the destination has enough compute, SQL capability, and concurrency to handle transformations directly.
  • ELT keeps raw landing visible, which makes recovery, re-modeling, and debugging easier than in opaque pre-load systems.
  • ELT is not just "load then run SQL"; it is a way of organizing ingestion, modeling, testing, and ownership.
  • ELT is not universal; it is a strong default for analytics stacks, not a law of nature.

Why ELT Won in the Cloud Era

ELT became the dominant pattern for many cloud-warehouse analytics stacks because cloud warehouses changed the tradeoffs that made classic ETL dominant. Storage got cheaper. Warehouse compute became elastic. SQL got more expressive. Teams wanted faster iteration and fewer proprietary transformation surfaces.

ShiftWhy it helped ELTOperational resultCheap destination storageTeams could afford to keep raw history in the warehouseFewer destructive pre-load transformationsElastic computeTransforms no longer required a separate always-on processing tierWarehouse-native modeling became practicalSQL-centric workflowsAnalysts and engineers could collaborate in one language and one repodbt and Git-based analytics engineering took offFaster schema iterationTeams could land raw data first and adjust transformations laterLess pressure to predict every semantic rule at ingestion time

That does not mean ETL disappeared because it was "wrong." It means ELT fit the new warehouse economics better for a large class of analytics workloads. Regulated pre-load transforms, stream-processing systems, and certain operational pipelines still need different shapes. For many warehouse-centric teams, though, keeping raw data in the destination and evolving business logic in versioned SQL turned out to be a faster, more legible way to work.

ELT Is an Operating Model, Not Just an Acronym

Teams often talk about ELT as if it were just the opposite of ETL. In practice, ELT is a broader operating model. It includes how data lands, how models are layered, how tests run, how backfills are done, and who owns business semantics after the first load succeeds.

  • Raw landing exists on purpose. The team chooses to preserve source fidelity before heavy interpretation.
  • Transforms live in reviewed code. SQL and tests become part of the delivery contract rather than ad hoc dashboard logic.
  • The warehouse is part of the runtime. Performance, costs, materializations, and query patterns matter because compute happens there.
  • Correctness is ongoing. Late data, backfills, reruns, and changing schemas have to be handled over time, not only on day one.

That is why a stack can technically "do ELT" and still be messy. If raw landing is unclear, the dbt project is inconsistent, and nobody knows where business logic belongs, the stack has ELT-shaped tools but not an ELT operating model.

What a Healthy ELT Architecture Looks Like

A healthy ELT stack usually has a simple, inspectable sequence from source to destination to models.

  • Discover the source shape. Know the tables, fields, types, and change surface before you try to model anything.
  • Load raw data into bronze. Preserve source fidelity and enough metadata to reason about freshness, history, and recovery.
  • Build silver staging and conformance logic. Fix names, types, timezones, keys, and reusable domain rules.
  • Build gold marts for stable business consumption. Present tables and measures that match how the business actually asks questions.
  • Test and validate the path. Catch shape issues, bad joins, duplicate keys, and metric drift before users do.
  • Operate the stack over time. Watch freshness, costs, late data, and changing source behavior.

The architecture is not clever. That is the point. ELT works well when the boundaries stay legible and the warehouse models are ordinary enough that another engineer can understand them without guessing where the real logic lives.

Raw Landing Principles That Stop Confusion Later

Strong ELT starts with a healthy raw landing layer. A lot of downstream confusion is really raw-layer confusion that nobody named early enough.

  • Raw means source-shaped, not analytics-ready. Bronze should preserve what arrived, not hide it behind premature business interpretation.
  • Raw needs metadata. Load timestamps, source identifiers, and replay or checkpoint context make recovery possible.
  • Raw should be inspectable. If nobody can explain what a bronze row means, silver and gold will drift too.
  • Raw should tolerate source evolution. Additive changes and type evolution should be visible rather than silently destructive.
  • Raw is not the consumer contract. It is the recovery and modeling foundation, not the final reporting surface.

Schema evolution is where this gets real. A new nullable source column can usually flow through bronze as an additive change. Nested structures should usually stay preserved in raw form until silver decides how to normalize them. Incompatible type shifts should not be silently treated as if nothing changed. They need an explicit evolution path or human review, because otherwise downstream models inherit ambiguity that looks like a warehouse bug later.

That is why the bronze layer in Skippr's docs matters. It keeps raw extracted data separate from silver and gold, which gives the modeling layer room to become more useful without erasing what the source actually produced.

How Bronze, Silver, Gold, and dbt Fit Together in ELT

One of the clearest versions of ELT uses a bronze, silver, gold layering model with dbt as the transformation framework on top.

LayerTypical contentsMain responsibilityBronzeRaw extracted tables, files, or append-only change dataPreserve source fidelity and support replay, inspection, and recoverySilverStaging models, normalized timestamps, cleaned keys, conformed entitiesMake data consistent and reusableGoldBusiness-facing marts, metrics, and serving tablesPresent stable analytical contracts to downstream users

dbt fits most naturally across silver and gold. Source definitions point at bronze, staging models clean and standardize in silver, and marts or domain models live in gold. That does not mean every stack needs those exact labels. It means the separation of concerns is usually worth keeping, because it stops raw recovery, cleanup work, and business semantics from collapsing into one hard-to-debug layer.

In Skippr's documented path, the runner drafts a standard dbt project after bronze landing and validates it against the destination. That gives the team a concrete silver and gold starting point instead of a blank modeling repo.

How ELT Transforms Are Materialized and Rerun

The transform layer is where many ELT stacks either become durable or quietly become expensive and wrong. The key choices are not abstract. They are things like view versus table versus incremental, when to full refresh, and how to rerun safely when a model or source assumption changes.

MaterializationBest fitStrengthWatch out forViewLight staging logic and low-cost reuseSimple to maintain and always currentPushes compute to query time and can stack into slow downstream queriesTableHeavy transforms and stable downstream servingPredictable query performanceFull rebuild cost can grow quicklyIncremental tableLarge facts that change over timeAvoids reprocessing the full model on every runNeeds a real answer for late data, deletes, reruns, and full refresh boundaries

A healthy ELT stack usually keeps staging models simple, makes heavy reusable transforms materialized where warranted, and treats incremental logic as a correctness contract rather than just a cost optimization. A bounded backfill, a full refresh, and an everyday incremental run are three different operations and should be described that way in the runbook.

The practical question is: if a source fix lands for data from last week, do you rebuild one model, one date range, or the whole downstream chain? Good ELT teams know that answer before the incident happens.

Batch, Incremental, and CDC Inside ELT

ELT is compatible with more than one load pattern. That is important, because teams sometimes talk as if ELT implies either batch only or CDC only. In practice, the load strategy depends on the source and freshness requirement.

PatternHow it fits ELTBest forWatch out forBatch snapshotLoad current-state slices into bronze, then transform in the warehouseSmall or slow-changing sourcesExpensive re-reads and weak delete semanticsIncremental batchLoad only new or changed rows based on source progress markersTimestamp-driven operational sourcesLate-arriving changes and naive watermarksCDC-backed ELTLoad ordered mutations into bronze or final-state tables, then model from stable downstream stateHigh-change sources that need low-latency warehouse freshnessResume state, delete handling, and apply correctness

The important distinction is that incremental sync and CDC final-state correctness are related but not identical stories. Incremental sync means the extract-and-load engine tracks source progress so reruns only process new or changed rows and only advance when the corresponding load commits durably. CDC correctness is stronger: supported source and destination pairs also need business keys, ordering metadata, replay behavior, and tombstone handling so retries and restarts converge on the correct downstream final state.

That is why CDC in ELT should not be described as "just faster ELT." It is a different correctness contract. A small SaaS admin table can land via incremental batch while a transactional orders table uses CDC, and both can still be part of the same ELT stack if the warehouse modeling surface stays coherent.

A Worked Example: PostgreSQL to Snowflake ELT

Use one real path to make the architecture concrete. Imagine a PostgreSQL application database feeding Snowflake for analytics. The ELT objective is to land raw source data in Snowflake, then model it into staging and marts with dbt.

A raw bronze row in Snowflake might look like this:

{ order_id: 8472, customer_id: 219, status: "PAID", total_cents: 129900, created_at: "2026-05-14 12:11:03-04", _loaded_at: "2026-05-14T16:11:14Z" }

A staging model in dbt can then do the warehouse-native cleanup that makes the row useful:

select order_id, customer_id, lower(status) as order_status, convert_timezone('UTC', to_timestamp_tz(created_at))::timestamp_ntz as created_at_utc, total_cents / 100.0 as order_total, _loaded_at from {{ source('raw', 'orders') }}

That silver model is where time normalization, naming, and type cleanup happen. A gold mart can then answer a business question much more directly:

select date_trunc('day', created_at_utc) as order_date, sum(order_total) as booked_revenue from {{ ref('stg_orders') }} where order_status = 'paid' group by 1

Validation is part of the example too. The dbt layer can assert that order_id is unique, that order_status contains only expected values, and that raw-to-stage row counts stay within known rules. That is ELT doing more than loading. It is making the analytical contract visible.

Keeping ELT Correct Over Time

The most underestimated ELT work starts after the first successful build. Sources change. Late data arrives. Incremental models need backfills. Costs spike. The system is only healthy if correctness survives over time.

  • Late-arriving data: some facts arrive after the reporting window they belong to, so incremental models need lookback rules or periodic rebuilds.
  • Incremental model semantics: every incremental model needs a clear answer for updates, deletes, reruns, and restatements.
  • Backfills and rebuilds: the team needs a safe path for "recompute this range" that does not corrupt current production models.
  • Rerun safety: retries should not duplicate rows or create double-counted marts just because a job was restarted.
  • Orchestration and dependency order: ELT jobs should run in a way that preserves source freshness expectations and downstream model assumptions.
  • Cost control: warehouse-native transforms are powerful, but repeated full refreshes and poorly chosen materializations become expensive quickly.

A useful mental test is: what happens if a refund for last Tuesday lands tonight? If the answer is "the mart stays wrong until the next manual fix," the ELT operating model is not mature yet.

How to Choose the Right Warehouse for ELT

ELT depends on the destination, so warehouse choice is not an afterthought. The best warehouse for ELT is the one whose compute model, SQL behavior, concurrency profile, governance surface, and cost shape match your workload.

Workload questionWhat to evaluateWhy it matters for ELTHow heavy are the transforms?Materialization behavior, caching, scaling model, temp storage patternsHeavy staging and marts can dominate total ELT costHow many users and jobs run at once?Concurrency model, queueing, workload isolationELT runs should not starve BI queries or vice versaHow much semi-structured data is involved?JSON support, nested types, file-format handlingRaw landing and early-stage ELT get easier when the destination handles mixed shapes wellHow strict is governance?Permissions, lineage, audit features, region controlELT becomes a production system, so governance cannot be bolted on late

There is no universal winner here. Snowflake is often attractive for clean warehouse isolation and mature SQL workflows. BigQuery is strong when scan-based economics and GCP-native operation fit the team. Databricks is compelling when lakehouse patterns and mixed data workloads matter. Redshift, Synapse, Athena, ClickHouse, and others each have real strengths for particular workloads. The right question is not "which platform is fashionable?" It is "which platform behaves well under our real ELT workload?"

Governance, Testing, and Privacy in a Real ELT Stack

ELT is sometimes sold as a speed story only. In production, it also needs governance, testing, and privacy boundaries. Otherwise the warehouse becomes fast but untrustworthy.

  • Testing: use schema tests, relationship checks, accepted values, and targeted business validations on important marts.
  • Documentation: model descriptions, column descriptions, and lineage matter because ELT creates many layers quickly.
  • Permissions: bronze should usually be more restricted than gold, because raw tables often expose source detail consumers do not need directly.
  • Privacy: decide where masking, hashing, or restricted attributes should live instead of relying on accidental query discipline.
  • Ownership: somebody has to own source health, somebody has to own model semantics, and somebody has to own incident response when freshness slips.

Skippr's docs are useful here because they keep the data boundary explicit. Row-level data stays on the machine running skippr and in the destination, while metadata is the default model input and the cloud path handles control-plane concerns. That is a cleaner operating story than "trust the black box."

When ELT Is the Wrong Tool

ELT is a strong default for modern analytics stacks, but it is not the right answer for every workload.

  • Use a more classic ETL path when data must be transformed or masked before it is allowed into the destination at all.
  • Avoid ELT-first thinking when the destination cannot handle the compute or concurrency profile the transform workload needs.
  • Avoid warehouse-heavy ELT when the team is not yet prepared to own cost discipline, tests, and model lifecycle.
  • Do not use ELT as an excuse to postpone semantic decisions forever. Raw landing is helpful, but it is not the same as a useful data model.
  • If the workload is tiny and static, a simpler scheduled load may be better than a full ELT operating model.

The point is not to defend ELT at all costs. The point is to use it where its strengths matter: fast iteration, visible raw landing, warehouse-native transforms, and a modeling surface that engineers can review and improve.

Common ELT Failure Patterns

ELT failures are repetitive, which is useful because repetitive failures are easier to design against.

  • Warehouse-first confusion: teams buy a warehouse and call it an ELT stack without solving discovery, loading, validation, or ownership.
  • Raw landing without contracts: bronze fills up quickly, but nobody can explain what is in scope or how downstream models should use it.
  • Hidden transformation logic: critical definitions live in BI tools instead of the reviewed model layer.
  • Incremental drift: models run faster over time but quietly stop being correct because late data or deletes were ignored.
  • Unbounded full refreshes: the stack works at ten tables and becomes a cost incident at two hundred.
  • Gold models built directly on raw tables: marts inherit source mess and become hard to stabilize.
  • No operating model for backfills and reruns: the team can launch ELT, but not safely repair it.

The pattern underneath these failures is simple: load happened, but the "transform and operate" parts stayed implicit.

How Skippr Fits a Practical ELT Stack

Skippr fits best when the goal is a concrete ELT path with visible phases and artifacts: discover the source, sync raw data into bronze, model a standard dbt project, and validate the result against the destination.

  • Documented phases: the public path in the docs is discover, sync, model, and validate rather than an opaque warehouse side effect.
  • Deterministic ingest path: schema discovery and destination mapping, type reconciliation and evolution handling, incremental checkpoints and replay behavior, and CDC reconciliation stay deterministic rather than model-guessed.
  • Generated artifacts: files such as dbt_project.yml, profiles.yml, models/schema.yml, models/staging/stg_*.sql, and packages.yml are written as normal dbt project assets you can inspect and extend.
  • Scoped AI input and data boundary: metadata is the default model input, data samples are optional and off by default, and row-level data only ever exists on the machine running skippr and in the destination while the cloud path handles authentication and control-plane services.

That is a strong fit for teams leaving behind manual SQL, fragile extracts, or stacks with too many boundaries between ingestion and modeling. What Skippr does not remove is the need to define business semantics, choose model ownership boundaries, and decide when a gold model is ready for consumers. Those remain engineering and analytics decisions.

For related reading, pair this guide with The Ultimate Guide to Data Migration, The Ultimate Guide to Change Data Capture, The Ultimate Guide to Data Modeling, The Medallion Architecture Guide, and the How It Works docs.

Your Practical ELT Checklist

If you want one section to keep open while designing the stack, use this one.

  • Decide whether the workload actually wants ELT rather than classic ETL or a simpler batch pattern.
  • Choose the destination based on compute model, SQL behavior, governance, and workload fit, not vague ecosystem familiarity.
  • Define the raw landing boundary and the metadata that must survive the extract and load path.
  • Make bronze, silver, and gold responsibilities explicit before you start building marts.
  • Pick the freshness model deliberately: batch, incremental, or CDC-backed ELT.
  • Keep transformation logic in reviewed, versioned SQL rather than in ad hoc BI queries.
  • Test both data shape and business outcomes, not just row counts.
  • Make ownership, documentation, and privacy boundaries explicit from the first useful version.
  • Treat generated assets as a starting point for a durable operating model, not as a substitute for business judgment.

That sequence reflects how strong ELT systems actually get built. First make the architecture legible. Then land one useful path. Then harden the model and operating contract before you widen the stack.