New · Cohort 4AI-Powered Data Engineering Cohort 4 goes live 26 September · only 40 seatsRegister Now
Data Engineering · Core Concepts

ETL Interview Questions: Concepts, Testing, and Scenarios

ETL concepts are the backbone of every data engineering interview regardless of tool — and ETL testing rounds draw on the same core. These 16 answers cover ETL vs ELT, CDC, idempotency, SCD handling, testing types, and the scenario questions that decide offers.

By Durgesh Yadav — Senior Data Engineer @ 7-Eleven · Updated 25 Jul 2026. Preparation guidance, not a hiring guarantee.

Jump to 34 answered questionsBeginner to Advanced · 4 FAQs · 3-part guide

What are the most asked ETL interview questions?

Expect ETL vs ELT, full vs incremental loads, CDC methods (timestamp, log-based, triggers), idempotency, SCD Type 1 vs Type 2, data quality checks, and source-to-target reconciliation testing. Indian service and product companies add scenario rounds — designing an incremental pipeline, safe backfills, and debugging a run that succeeded but produced wrong numbers.

Guide

What To Learn And How To Practice

Which ETL concept questions filter candidates?

The opener is almost always ETL vs ELT, followed by load strategies and CDC. Interviewers listen for tradeoffs and a concrete stack, not tool names recited from a course — a candidate who explains when full load is still correct beats one who claims incremental is always better.

ETL vs ELT with a real stack (Informatica vs Snowflake + dbt) beats a textbook definition
Full vs incremental: know when full load is still the right choice
All four CDC approaches with tradeoffs — timestamp, log-based, trigger, snapshot-diff

What does the ETL testing round cover?

If the role says ETL tester or the JD mentions reconciliation or QuerySurge, expect a dedicated testing round; developers get the same questions phrased as "how do you validate your pipeline". Either way, the reconciliation ladder — counts, sums, hashes — is the answer skeleton.

Source-to-target reconciliation: row counts, then column sums, then hash comparison
Incremental-load testing: only the delta moved, and reruns don't duplicate
Know MINUS/EXCEPT queries plus one framework — dbt tests or Great Expectations

How do you handle ETL design and debugging scenarios?

Product companies and GCCs decide on scenarios: incremental pipelines without clean change columns, safe backfills on live pipelines, and green-but-wrong debugging. Structure wins — state assumptions, pick an approach with its tradeoff, and close with the check that prevents recurrence.

Always state assumptions first: volume, change indicators, SLA, delete handling
Prove idempotency in every design — it is the most common follow-up
Close debugging answers with the data-quality check you would add

Question bank

34 interview questions with answers

Real questions from beginner to advanced, each with a concise model answer — practice them, then rehearse live in a mock interview. Every answer is open; collapse any you have already covered.

EasyWhat is the difference between ETL and ELT?

ETL transforms data on a separate engine before loading the warehouse (Informatica, SSIS, Spark); ELT loads raw data first and transforms inside the warehouse using its MPP engine — Snowflake, BigQuery, or Synapse, typically with dbt as the transform layer. ELT dominates cloud stacks because storage is cheap, warehouse compute scales, and raw data stays available for reprocessing. A sharp addition: ELT shifts data-quality and governance checks to after the load.

EasyFull load vs incremental load — when is full load still the right choice?

Full load truncates and reloads everything; incremental moves only new or changed rows using a watermark or CDC. Full load remains correct for small dimension tables, sources with no reliable change indicator, or when the reload window is trivial — simplicity beats maintaining change-detection logic. Incremental becomes mandatory when volume or load windows make full reloads impossible.

EasyWhat is a staging area, and why not load targets directly?

A staging layer holds raw extracted data before transformation — it decouples extraction from transformation, lets you reload and debug without hitting the source again, enables reconciliation against the source, and isolates source outages. In modern lakehouse terms this is the raw or bronze zone. Loading targets directly means any transform bug forces re-extraction, and you lose the audit trail.

EasyWhat data quality checks do you build into a pipeline?

The standard set: row-count and checksum reconciliation between source and target, not-null and uniqueness checks on keys, referential integrity between facts and dimensions, accepted-range and domain checks, and freshness checks confirming today's partition arrived. Make critical rules blocking (fail the pipeline) and the rest warning-level, implemented with dbt tests, Great Expectations, or plain SQL assertions.

EasyWhat does an orchestrator like Airflow or ADF actually do beyond scheduling?

It manages dependencies (task B only after A), retries with backoff, alerting, backfills, parameterized runs, and concurrency control, plus a monitoring surface for run history. Cron only answers "when"; an orchestrator answers "in what order, what happens on failure, and how do I rerun window X". That distinction is exactly what the interviewer is probing.

MediumCompare the CDC approaches: timestamp column, log-based, triggers, and snapshot diff.

Timestamp/watermark: simplest, but misses hard deletes and rows updated without touching the column. Log-based (Debezium, SQL Server CDC, Oracle GoldenGate) reads the transaction log and captures inserts, updates, and deletes with minimal source impact — the production-grade answer. Triggers write change rows on DML — reliable but they add write latency and DBAs resist them. Snapshot diff (full extract plus hash compare) is the fallback when the source offers nothing: expensive but complete, including deletes.

MediumWhat makes a pipeline idempotent, and why does it matter?

Idempotent means rerunning the same run or window produces the same end state — no duplicates, no double counting. Standard techniques: delete-then-insert or overwrite scoped to the partition (usually a date), MERGE/upsert on business keys, or run-scoped keys with dedupe on load. It matters because retries and backfills are inevitable; a non-idempotent pipeline turns every recovery into a data-corruption incident.

MediumHow do you implement SCD Type 2 in a pipeline?

Compare incoming rows to the current dimension version, typically via a hash of the tracked attributes. Unchanged rows are skipped; changed rows expire the current version (set end_date, is_current = false) and insert a new version with a fresh surrogate key and effective_date; new keys are plain inserts. In SQL this is a MERGE — often two-step UPDATE plus INSERT, since MERGE cannot perform both actions on one matched row; in Delta Lake it is MERGE with a union trick for the insert leg.

MediumWhat ETL testing types should a tester or data engineer know?

Source-to-target count and reconciliation testing (counts, sums, hash or checksum comparison), transformation-logic testing against mapping documents, duplicate and null checks on keys, incremental-load testing (only the delta moved, and reruns don't duplicate), SCD/history testing, regression testing after changes, and performance testing against the load window. Always name a method or tool: MINUS/EXCEPT queries, QuerySurge, dbt tests, or Great Expectations suites.

MediumDescribe your error-handling strategy: what retries, what fails, what quarantines?

Classify errors first. Transient failures (network, deadlock, throttling) get automatic retry with capped exponential backoff. Data errors (bad rows, type violations) shouldn't fail the batch — route them to a reject or dead-letter table with reason codes and load the rest, with a threshold that fails the run if the reject percentage spikes. Structural errors (schema change, missing file) fail fast and alert, because retries cannot fix them; every failure path emits an alert with run context.

MediumHow do you run a backfill safely on a live pipeline?

The prerequisite is idempotency — partition overwrite or MERGE. Parameterize the pipeline by date window rather than "now", run backfill windows with controlled parallelism so you don't crush the source or the warehouse, ideally via a separate backfill job so daily SLAs aren't blocked, and bypass or restore watermarks deliberately. Reconcile each window after it lands and tell consumers in advance, because historical numbers will visibly change.

MediumHow do you reconcile source and target at scale, beyond row counts?

Use a layered approach: row counts per partition, then SUM/MIN/MAX on numeric and date columns, then aggregate hash comparison — MD5 or HASHBYTES over concatenated normalized columns, grouped by key ranges to localize mismatches — and only then row-level EXCEPT/MINUS on the ranges that differ. Counts alone will pass even when rows are corrupted in place, which is exactly why interviewers push past them.

HardThe source table has no updated_at column, no CDC, and 500 million rows. How do you load it incrementally?

In order of preference: enable log-based CDC (SQL Server CDC or Change Tracking, Debezium) — the right fix, but it needs DBA buy-in; hash-diff — stage current keys plus a row-hash, compare against the previous snapshot's hashes to derive inserts, updates, and deletes, which reads everything but moves only the delta; or partition-scoped reloads if the data is append-mostly by date. State the tradeoff explicitly: hash-diff trades source read cost for full correctness, including deletes.

HardExplain exactly-once vs at-least-once delivery, and how you achieve effective exactly-once.

Most movement layers give at-least-once — retries can redeliver the same data. True exactly-once across heterogeneous systems is impractical, so you achieve effective exactly-once by pairing at-least-once delivery with an idempotent sink: MERGE on business keys, partition overwrite, or transactional writes that record offsets or run IDs (Kafka offsets committed atomically with the write, Delta transaction IDs). The pattern name is the interview answer: at-least-once delivery plus an idempotent consumer.

HardHow do you handle late-arriving and out-of-order data in aggregates and SCD Type 2?

For aggregates, reprocess a sliding lookback window — recompute the last N days each run with partition overwrite so late rows land correctly — and watermark on event time, not load time. For SCD2, a late change dated before the current version means inserting a version into history and adjusting adjacent effective and end dates, which is expensive; many teams accept load-time ordering and document the limitation. In streaming terms: watermarks with allowed lateness, and truly late data routed to a correction path.

HardScenario: the pipeline is green but the dashboard numbers are wrong. Walk me through debugging.

Work backwards through lineage: define what "wrong" means with a reconciliation query against source for the affected slice, then check the usual suspects — duplicate loads from a rerun without idempotency, timezone or partition-boundary bugs (IST vs UTC cutoffs are a classic in India-based teams), late data that arrived past the watermark, silently changed source semantics, and join fanout or filter changes in the transform. Fix it, then add the blocking data-quality check that would have caught it — interviewers listen for that closing move.

hardThe DAG is green and row counts reconcile, but finance says revenue is off by 0.3%. How is that possible, and how do you find it?

Green only means the code ran without throwing, and row counts are the weakest check there is because they survive any corruption that does not change cardinality. A value-level gap on matching counts points at a handful of suspects: a join fanout later collapsed by a DISTINCT, a unit or currency mismatch (paise loaded as rupees, a new currency code defaulting to INR), rows landing in the wrong day because the source stamps IST and the pipeline buckets on UTC, a numeric cast losing precision, or a filter dropping NULLs silently. Debug by narrowing, not by reading code: compare source and target SUMs by day, then by region or channel, until the delta collapses into one slice, then diff those rows. Close by adding the sum and hash reconciliation test that counts could never give you.

mediumHow do you handle schema drift from a source, and how do you know what it breaks downstream?

Split drift into additive and breaking, and automate only the additive half. A new nullable column or a new enum value should be absorbed: land raw with a schema-evolving format (Delta or Iceberg mergeSchema, or raw JSON projected in a staging model), log the change, move on. Breaking changes — a dropped or renamed column, a narrowed type, a semantic change like an amount switching units — should fail loudly and quarantine the batch rather than write NULLs into a fact table. What breaks is a lineage question. Table-level lineage tells you which models and dashboards touch the object; column-level lineage tells you whether the changed column is actually used, which is the difference between notifying two teams and notifying forty. dbt's DAG plus exposures, OpenLineage, or Purview and Collibra in enterprises give you that map.

mediumWhat is a data contract, and who actually enforces it?

A data contract is a versioned, explicit agreement between the producing system and the consuming pipeline covering schema and semantics: field names and types, nullability, the primary key and grain, allowed enum values, freshness and volume SLA, PII classification, and a deprecation notice period. Enforcement is the whole point. The contract lives beside the producer's code — a schema file in their repo, or an Avro/Protobuf entry in a schema registry for Kafka topics — and their CI fails when a change violates it, backed by a runtime check that quarantines non-conforming payloads instead of loading them. The hard part is organisational: in most Indian setups the producer is another product team or a vendor with its own roadmap, so contracts only stick when one team owns the platform SLA and the contract is what they point at.

mediumWhat makes a well-designed Airflow DAG, and what should Airflow not be doing?

A good DAG is idempotent and parameterised by the run's data interval rather than datetime.now(), so any window can be rerun or backfilled and produce the same result. Tasks are the unit of retry: one logical step each, small enough to rerun cheaply, with retries, an SLA, and no hidden ordering assumptions between them. Operators do work, sensors wait — use reschedule mode or deferrable operators with a timeout, because a poking sensor holds a worker slot for hours — and XComs pass small metadata like a file path, a watermark, or a row count, never the data itself. What Airflow should not be is the processing engine. Pulling a million rows into a PythonOperator turns your scheduler into a single-node ETL server. Push compute to the warehouse, Spark, or dbt and let Airflow orchestrate.

easyWhat is dbt and where does it fit in an ETL stack?

dbt is a transformation framework, not a data-movement tool: it takes SQL you already write and adds Jinja templating, dependency resolution through ref(), version control, tests, and documentation, then executes all of it inside the warehouse. It is the T in ELT — something else lands raw data (Fivetran, ADF, Airbyte, a Spark job), dbt builds staging, intermediate, and mart models on top, and an orchestrator triggers dbt run. What earns credit in interviews is the boundary: models are just SELECTs materialised as views, tables, incrementals, or ephemeral CTEs, snapshots give you SCD Type 2 without hand-written MERGE, and tests are assertions you can run in CI. Saying dbt processes data is the tell that you have only read about it — the warehouse does every bit of the compute.

easyInformatica and SSIS versus Airflow, dbt and Spark — why do Indian enterprises still run both?

Because the two stacks optimise for different things and the older estates still run the business. GUI tools give you drag-and-drop mappings, a wide connector library, a vendor support contract, and a large pool of trained developers — exactly what a bank or insurer with a decade of Informatica mappings and an audit history wants. Code-first stacks give you Git, code review, tests, CI/CD, metadata-driven pipelines generated in a loop, and no per-core licence — what a product company or GCC building something new wants. Services firms therefore staff both: legacy maintenance and migration on one side, greenfield Airflow, dbt, and Spark on the other. Say it plainly: the concepts do not change — CDC, SCD, idempotency, reconciliation are identical — so you pick the tool the team that gets paged at 2am can actually run.

easyWhere does Azure Data Factory fit, and what are its core concepts?

ADF is Azure's orchestration and data-movement service — the cloud successor to SSIS for scheduling and copying, not an engine you write heavy transformation logic in. Five concepts carry most rounds. Linked services are the connection: endpoint plus credentials, ideally from Key Vault. Datasets describe the shape and location of data at that connection. Pipelines hold activities: Copy, Lookup, ForEach, Execute Pipeline, Stored Procedure. Integration runtimes are the compute doing the movement — Azure IR for cloud-to-cloud, self-hosted IR when the source sits behind an on-prem firewall, SSIS IR to lift existing packages. Triggers start it all: schedule, event-based on blob arrival, and tumbling window, which is the one that gives you per-window retry and clean backfills. Real transformation belongs in Databricks, Synapse, or SQL; mapping data flows run Spark underneath and are priced accordingly.

mediumYou are choosing the stack for a new mid-size data platform — warehouse or lakehouse, and what changes about the ETL?

Default to a managed warehouse unless you have a reason not to: Snowflake, BigQuery, or Databricks SQL, a managed connector for standard SaaS sources, dbt for transforms, one orchestrator, one BI tool. A mid-size team's binding constraint is people, not technology — three engineers cannot operate self-hosted Kafka, Spark, and Airflow as well as they can operate SQL. Choose a lakehouse on Delta or Iceberg when you have high-volume semi-structured data, ML workloads reading the same tables, or a cost profile that hates warehouse compute. ETL then differs in the mechanics: an update is a MERGE that rewrites data files rather than rows, so you schedule compaction and vacuum or the small-files problem eats your read performance; schema evolution is a table property; and time travel makes verifying a backfill genuinely easy.

hardCustomer data lives in CRM, billing and support, and the three disagree. How do you build one customer view?

Treat it as entity resolution plus survivorship, and make both explicit and auditable. Standardise before matching — lowercase and trim emails, normalise Indian phone numbers to a +91 form with the leading zero stripped, uppercase and validate PAN or GSTIN, tokenise addresses — because a lot of apparent duplicates are only formatting. Then match in tiers: deterministic on strong identifiers first (GSTIN, PAN, verified email or phone), then fuzzy on name plus address with a scored threshold, and route the grey band to a human review queue instead of auto-merging. Survivorship is a documented rule per attribute, not per record: billing wins legal name and address, CRM wins owner and segment, support wins last contact channel, most-recent non-null otherwise. Keep a crosswalk of source keys to master ID so any merge can be explained and reversed.

hardA nightly job takes six hours and the business wants it in two. How do you approach it?

Measure first — get per-stage timings, because the time is almost always concentrated in one stage and a candidate who opens with add more cluster fails this question. Then work in order of leverage. Stop moving data you do not need: incremental instead of full extract, column pruning, predicate pushdown to the source. Fix the shape of the work: file sizes and partitioning, skew on a hot key, a broadcast join instead of a shuffle, set-based SQL instead of row-by-row cursors or per-row API lookups. Parallelise branches that were serial for no reason. Only then buy compute for that window. Also challenge the requirement — usually one report needs the 2am number and the rest can wait, so splitting the DAG into a critical path and a long tail delivers the SLA without touching the slow part.

mediumYour pipeline only does inserts and updates, but the source hard-deletes rows. How do you handle that?

You have to detect deletes explicitly, because a MERGE on business keys will never see a row that no longer exists. The right fix is log-based CDC — Debezium or SQL Server CDC — which emits delete events with the change type. When the source only gives you a full key extract, reconcile key sets and soft-delete the misses.

sql
UPDATE dim_customer t
SET is_deleted = TRUE, deleted_at = CURRENT_TIMESTAMP
WHERE t.is_deleted = FALSE
  AND NOT EXISTS (
    SELECT 1 FROM stg_customer_keys s WHERE s.customer_id = t.customer_id
  );

Soft-delete rather than physically delete, so existing facts still join and history survives. Guard it hard: if the extract was partial or staging is empty because the load failed, that statement wipes the dimension, so abort when the key count drops beyond a threshold.

mediumHow do you ingest from a third-party API that rate-limits you and fails randomly?

Design for the API being unavailable and the run being resumed, not for the happy path. Stay under the documented limit with a token bucket or a fixed delay, and honour the Retry-After header on a 429 instead of guessing. Retry with exponential backoff plus jitter on 429s, 5xx, and timeouts, never on 4xx client errors, with a capped attempt count. Set connect and read timeouts on every call — an un-timed-out socket is how a twenty-minute job becomes a job that hangs for days without anyone noticing. Page with a cursor and checkpoint that cursor after each successful page so a resume does not start from zero, and land raw responses to object storage before parsing so you can replay without re-calling. Finally MERGE on the provider's own record id, because retries will redeliver rows.

hardTwo pipelines write to the same table and have started overwriting each other. How do you fix it?

The real fix is single ownership — one table, one writing pipeline — and everything else is mitigation. Where two writers are genuinely needed, partition the writes so they never touch the same rows: pipeline A owns source system X's partitions, B owns Y, and each does a partition-scoped overwrite rather than replacing the whole table. If they must touch the same rows, you need concurrency control the storage layer actually offers: Delta and Iceberg give optimistic concurrency with commit conflict detection, a warehouse gives you a transaction, and a plain directory on object storage gives you nothing at all. Add an orchestration-level mutex so overlapping runs queue instead of racing (an Airflow pool of size one, or a lock row in a control table), and stamp a run_id on every row so you can prove which run wrote what.

hardWrite the SQL that maintains an SCD Type 2 dimension.

A single MERGE cannot both expire the old version and insert the new one for the same key, so the production pattern is expire-then-insert, driven by a hash of the tracked attributes.

sql
MERGE INTO dim_customer t
USING stg_customer s
  ON t.customer_id = s.customer_id AND t.is_current
WHEN MATCHED AND t.row_hash <> s.row_hash THEN UPDATE
  SET t.is_current = FALSE, t.end_date = s.effective_date - 1
WHEN NOT MATCHED THEN INSERT (customer_id, name, city, row_hash, effective_date, end_date, is_current)
  VALUES (s.customer_id, s.name, s.city, s.row_hash, s.effective_date, DATE '9999-12-31', TRUE);

A second statement then inserts fresh versions for the keys you just expired. The probes that follow: the surrogate key is generated, not the business key; decide whether end_date is exclusive or the previous day and stay consistent; and the hash comparison is what makes a rerun a no-op.

hardThe same order sometimes arrives twice within five minutes. Write the deduplication.

This is a windowed dedupe, not a DISTINCT — the same order_id can legitimately reappear hours later as a genuine repeat event, so you compare each row to the previous row for that key.

sql
WITH flagged AS (
  SELECT *,
         LAG(created_at) OVER (PARTITION BY order_id ORDER BY created_at) AS prev_at
  FROM raw_orders
)
SELECT * FROM flagged
WHERE prev_at IS NULL
   OR created_at - prev_at > INTERVAL '5 minutes';

LAG keeps the first event of each burst and drops the echoes, where ROW_NUMBER would keep only one row per order ever. Two edges decide whether it survives production: identical timestamps need a deterministic tiebreaker in the ORDER BY, and if a burst can straddle a batch boundary you must read a few minutes back from the previous partition.

hardYou are migrating a large on-prem SSIS estate to the cloud and reports cannot go down. How do you sequence it?

Run both stacks in parallel and cut over report by report — never big-bang. Inventory first: packages, their real sources, their actual schedules, and who consumes the output, because estates like this always contain packages feeding reports nobody opens, and deleting those is the cheapest migration you will ever do. Then decide lift-and-shift versus rewrite per package: SSIS integration runtime inside ADF moves you fast with the technical debt intact, while rewriting into ADF plus dbt or Databricks is slower but is the reason you are migrating. Dual-run next — old pipelines keep feeding today's reports while the new ones write to a parallel schema, reconciled daily on counts, sums, and hashes until they agree through a full cycle including month-end close. Repoint BI one report at a time, keep the old path warm for rollback, then decommission.

mediumWhat do you monitor on a pipeline, and how do you alert without everyone ignoring the alerts?

Two layers. Pipeline health: freshness of the newest row against its SLA, success rate, run duration versus its normal distribution, rows in versus rows out, retry counts, and cost per run — duration drift is the metric that warns you before an incident rather than after. Data quality: the standard dimensions expressed as tests — completeness (nulls, missing partitions), uniqueness on keys, validity (ranges, enums, formats), consistency (target totals reconcile to source), accuracy against a trusted reference, and timeliness. Fatigue is an ownership problem, not a tooling one. Give every check a severity, page a human only for blocking failures on tables that feed money or a regulator, send the rest to a channel or dashboard, alert on the SLA being missed rather than on every retry, and delete any alert nobody has acted on in a month.

hardHow do you protect PII as it moves through the pipeline, including India's DPDP right to erasure?

Classify at ingestion and carry the classification along the lineage, because you cannot protect or erase what you cannot locate. Tag PII columns in the catalog, encrypt in transit and at rest, mask or tokenise in non-production instead of copying a raw prod dump into dev, and give analysts masked views rather than blanket table access. Minimise first — the safest PII is the field you never copied. Erasure is the hard engineering part, because warehouses are append-only by design: you need a person-to-key map, deletion propagated to every downstream copy including exports and backups, real removal from the files (a MERGE delete plus VACUUM on Delta or Iceberg, not a soft flag), and an audit record proving it happened inside the SLA. Crypto-shredding — tokenise identifiers, destroy the key — plus a documented retention window is the usual pattern.

By company

Analytics Engineer interviews that ask these questions

See how this topic shows up in real Analytics Engineer loops — rounds, difficulty and company-specific questions:

All company interview guides →

FAQ

Common Questions

Are ETL testing interview questions different from ETL developer questions?

About seventy percent overlap. Testers get deeper mapping-document validation, reconciliation methods, and test-case design; developers get the same concepts framed as design questions, like "how do you make this rerun-safe". Prepare the reconciliation ladder and idempotency either way — this page covers both framings.

Which ETL tools should I name in an Indian interview?

Match the JD. Services companies still run Informatica, Talend, SSIS, and ADF heavily; GCCs and product companies expect Airflow, dbt, and Spark. The concepts — CDC, SCD, idempotency, reconciliation — transfer across all of them, and interviewers reward concept depth over tool trivia.

Is ETL obsolete now that everyone says ELT?

No. The transform moved into the warehouse, but every concept here — incremental loads, CDC, data quality, SCD — applies unchanged to ELT stacks like Snowflake plus dbt. "ELT is ETL with the transform pushed onto warehouse compute" is a perfectly good interview line.

How are scenario questions asked in ETL interviews?

As open designs: "500-million-row table with no timestamp column, load it daily" or "the pipeline succeeded but the dashboard numbers are wrong". State assumptions, choose a CDC approach and name its tradeoff, prove the design is idempotent, and end with the data-quality check you would add.

Next Step

Turn The Guide Into Practice

Use PrepNPlaced tools to turn this learning path into resume proof, targeted practice, and interview-ready explanations.

Practice AI Mock Interview