Data Engineer Top 100 Interview Questions
100 data engineer interview questions with structured answers, comparison tables, flow diagrams, worked calculations and runnable examples. Covers SQL, data modeling, ingestion, storage, distributed processing, streaming, Python, data quality, governance and system design, from fundamentals to production operations.
Questions 41-60 of 100
Q41.How would you model orders, line items, payments, and refunds for analytics?
I would model each business process at its own grain and connect them through stable identifiers. Orders, purchased items, payment attempts, and refunds have different lifecycles.
- Define separate records for orders, order lines, payment transactions, and refund events, with source identifiers and authoritative business timestamps.
- Store product and customer context through governed dimensions, and define how discounts, taxes, currencies, and order-level charges are allocated.
- Link refunds to their original payment or item where the source supports it, preserving partial refunds and failed payment attempts explicitly.
- Publish summaries at a declared common grain and reconcile booked revenue, collected cash, and refunded amounts as distinct business measures.
flowchart TD A["Order header"] B["Order lines"] C["Payment transactions"] D["Refund events"] E["Grain aligned summaries"] F["Revenue and cash reporting"] A --> B A --> C C --> D B --> E C --> E D --> E E --> FTrade-offs:
- Separate process facts require deliberate joins but preserve distinctions that a single flattened table can obscure.
- Allocated charges simplify product reporting only when the allocation rule is documented and reproducible.
Example
An order contains two items, two payment attempts, and a later partial refund.
- Keep both attempts, with only the successful attempt contributing to collected cash.
- Record the refund as its own event linked to the original transaction.
- Report gross sales, cash collected, and refunds separately.
- Derive net measures using the agreed business definitions and reporting dates.
Q42.How would you reconcile source data with a transformed warehouse table?
I would compare both sides over the same business population and consistency boundary. A matching total row count alone cannot prove that the correct records arrived.
- Fix the source snapshot or cutoff, business interval, inclusion rules, units, and treatment of updates and deletes before comparing results.
- Compare control totals such as row counts, distinct identifiers, important amounts, and minimum or maximum event positions by meaningful partition.
- Investigate mismatches with key-level comparisons and sampled field checks, tracing transformations, filtering, joins, and duplicate handling.
- Document legitimate differences, repair unexplained ones, and store reconciliation evidence with the published dataset version or pipeline run.
flowchart TD A["Align cutoff and business rules"] B["Compare partition controls"] C{"Controls agree?"} D["Perform targeted key checks"] E["Investigate and repair"] F["Record reconciliation evidence"] A --> B B --> C C -->|yes| D C -->|no| E E --> B D --> FTrade-offs:
- Detailed row comparisons provide stronger evidence but can be expensive across very large datasets.
- Checksums accelerate detection only when serialization is consistent; matching hashes are not a mathematical guarantee of equality.
Example
Both systems contain 10,000 orders, but warehouse revenue is lower.
- Compare revenue by business day and currency.
- Locate the affected partition and compare order identifiers and amounts.
- Find that an update was missed while another order was duplicated.
- Repair both records and recheck counts, unique keys, and amounts.
Q43.When should a pipeline use a full refresh instead of an incremental load?
A full refresh rebuilds the target from the selected source population. An incremental load applies only new or changed information since a recorded boundary.
Full refresh Incremental Advantage: straightforward reconstruction Advantage: less repeated processing Challenge: repeated source and compute cost Challenge: correct change and delete handling When to use which:
- Use a full refresh for small datasets, initial loads, substantial transformation changes, or sources that cannot expose reliable changes within the required operating budget.
- Use incremental processing when volume or freshness makes rebuilding expensive and the source provides dependable identifiers, ordering, and change detection.
- Combine incremental delivery with periodic reconciliation or controlled rebuilds to detect drift and recover from historical defects.
An incremental strategy must account for updates, deletes, late commits, and retries. Filtering only on a creation timestamp is sufficient only for a genuinely immutable append-only source.
Q44.What is change data capture, and how does it differ from polling current rows?
Change data capture, or CDC, exposes inserts, updates, and deletes as changes that downstream systems can consume. Log-based CDC reads committed database changes from a supported change log.
- Information: a change normally includes record identity, operation type, ordering metadata, and available before or after values, depending on source capabilities and configuration.
- Comparison: polling current rows can miss intermediate changes and hard deletes unless the source exposes suitable timestamps, tombstones, or another change mechanism.
- Continuity: consumers must persist their position and keep up with log retention; losing the required history can force a new consistent snapshot.
- Operations: monitor source impact, connector permissions, schema changes, and lag, and account for redelivery when applying changes downstream.
CDC transports change evidence; it does not by itself guarantee correct target merges, business transformations, or end-to-end exactly-once effects.
Q45.How would you combine an initial database snapshot with ongoing CDC without gaps?
I would use a snapshot procedure coordinated with a known change-log position. Taking an ordinary table export and later starting an unrelated stream can lose or duplicate changes.
- Select a source-supported snapshot mechanism that establishes a consistent view and a corresponding position in the retained change log.
- Keep changes from the required boundary available while snapshot rows are copied, buffering or replaying overlap according to the capture protocol.
- Apply snapshot and change records using stable keys and ordering metadata, so overlap cannot overwrite a newer value with an older one.
- Validate the target at a known catch-up boundary, then continue consuming changes and persist progress only after durable target application.
flowchart TD A["Establish consistent snapshot boundary"] B["Copy snapshot rows"] C["Retain overlapping change log"] D["Apply ordered changes"] E["Reconcile at catchup boundary"] F["Continue live consumption"] A --> B A --> C B --> D C --> D D --> E E --> FTrade-offs:
- Long snapshots require enough log retention and can increase source resource pressure.
- Concurrent snapshot protocols reduce disruption but need precise overlap handling rather than guessed timing.
Example
A customer changes address while the initial snapshot is being copied.
- The snapshot boundary determines which version belongs to the snapshot.
- Retain the change event associated with the later update.
- Apply both according to source ordering, tolerating any documented overlap.
- Verify the final target address matches the source at the catch-up position.
Q46.How would you build a safe timestamp-based incremental extraction?
I would use a persisted extraction boundary and a repeatable target merge, while recognizing that timestamps may not capture every committed change. Source transaction behavior determines the remaining risk.
- Verify that the chosen timestamp changes on every relevant update, has adequate precision, and has a documented relationship to commit visibility.
- Record an upper extraction boundary and read a bounded interval, using a stable tie-breaker for equal timestamps when paging through results.
- Apply an intentional overlap and deduplicate or merge by source key, then advance the saved boundary only after durable target completion.
- Reconcile periodically and define a separate deletion mechanism; choose log-based capture if arbitrarily late commits or missing updates cannot be bounded.
flowchart TD A["Read saved boundary"] B["Set upper extraction boundary"] C["Read bounded overlapping interval"] D["Merge records by source identity"] E{"Target committed?"} F["Advance boundary"] G["Retry same interval"] A --> B B --> C C --> D D --> E E -->|yes| F E -->|no| G G --> CTrade-offs:
- Overlap improves tolerance to bounded delays but increases repeated reads and is not a guarantee against unlimited late commits.
- A timestamp-based extractor is simple only when the source’s update and deletion semantics support it.
Example
Two updates share the same timestamp, and a page ends after the first.
- Retain both timestamp and stable record key as the page cursor.
- Resume using their combined ordering so the second update is not skipped.
- Re-read the configured overlap on the next run and merge by identity.
- Advance the durable interval boundary only after successful publication.
Q47.How would you make a data load idempotent?
An idempotent load produces the same intended target state when the same input is applied repeatedly. This is essential because failures can leave the outcome of a previous attempt uncertain.
- Define stable input identity, such as an event identifier, source sequence, or partition and version, independently of the execution attempt.
- Choose an appropriate write strategy: deterministic replacement of a bounded partition, a keyed upsert, or a transactional event ledger with uniqueness checks.
- Publish data and progress through a consistent commit mechanism, avoiding blind appends when the previous write may already have succeeded.
- Test retries after partial work, after target commit, and before acknowledgment, including concurrent attempts and replay of older source versions.
flowchart TD A["Read identified input"] B{"Already applied?"} C["Return existing outcome"] D["Prepare deterministic target changes"] E["Commit data and processing record"] F["Acknowledge completion"] A --> B B -->|yes| C B -->|no| D D --> E E --> FTrade-offs:
- Tracking processed identifiers consumes storage and needs retention aligned with the possible replay horizon.
- Replacing a partition is straightforward only when the input fully defines that partition’s intended contents.
Example
A batch commits 5,000 events, but its completion acknowledgment is lost.
- The retry uses the same stable event identifiers.
- A target uniqueness rule or committed batch ledger recognizes the prior application.
- The retry confirms completion without adding another 5,000 rows.
- Downstream totals remain unchanged across repeated attempts.
Q48.How should a pipeline handle schema evolution?
Schema evolution is the controlled change of fields, types, and structure while producers and consumers continue operating. A change is safe only relative to the consumers that must read it.
- Compatibility: assess whether older readers can consume new data and whether newer readers can consume retained older data; these are different directions of compatibility.
- Additions: optional fields with meaningful defaults are often easier to introduce, but nullability and default interpretation must be agreed rather than assumed.
- Breaking changes: renames, removals, type narrowing, and changes in units or meaning may require versioned contracts and a migration period.
- Deployment: validate representative old and new records, coordinate producer and consumer rollout, and preserve a rollback or replay strategy.
Automatically accepting every new column can keep ingestion running while silently changing downstream semantics, so structural flexibility should not replace review of business meaning.
Q49.What should a data contract contain?
A data contract defines the promises between a dataset producer and its consumers. It should cover meaning and operating expectations as well as the physical schema.
- Structure and identity: specify fields, types, nullability, keys, uniqueness, event identity, and supported versions so records can be interpreted consistently.
- Semantics: define units, business meaning, valid values, timezones, update and deletion behavior, and any ordering guarantees that consumers rely on.
- Service expectations: describe publication frequency, freshness and completeness targets, retention, and how incidents or delays are communicated.
- Ownership and change: name the responsible team, compatibility rules, approval or notification process, and deprecation policy for breaking changes.
Enforce machine-checkable requirements during ingestion and deployment, while keeping human-readable definitions close to the dataset. A contract that nobody monitors will not prevent silent upstream changes.
Q50.How would you handle malformed records without silently losing data?
I would separate valid records from failures according to an explicit quality policy and retain enough evidence for repair. Whether the batch can continue depends on the failed rule’s business impact.
- Validate required structure, identifiers, types, and important business constraints before records reach trusted serving tables.
- Send invalid records to a restricted quarantine with source location, rule failure, ingestion metadata, and an appropriate retention policy.
- Choose whether to stop publication or release the valid subset based on agreed completeness and severity thresholds, reporting the rejected population.
- Repair the producer or transformation, then replay corrected records through the same idempotent path and reconcile the original input population.
flowchart TD A["Validate incoming record"] B{"Required checks pass?"} C["Write accepted records"] D["Record restricted quarantine entry"] E["Assess publication threshold"] F["Repair and replay failures"] A --> B B -->|yes| C B -->|no| D C --> E D --> E D --> FTrade-offs:
- Continuing with valid records improves availability but can create biased or incomplete analytics if rejection is not visible.
- Quarantine supports recovery but must not become an uncontrolled copy of sensitive source data.
Example
A feed contains 990 valid orders and 10 records with invalid identifiers.
- Record all 1,000 input positions.
- Quarantine the 10 failures with restricted access and clear reasons.
- Publish the 990 only if the agreed policy allows a partial result.
- Replay corrected records and reconcile the final accepted total to 1,000.
Q51.How do offset pagination and cursor pagination differ for data extraction?
Offset pagination skips a requested number of rows. Cursor pagination resumes from a supplied token or ordered position, which can be more stable and efficient for large sequential extracts.
Offset Cursor Resumes by the count of rows to skip Resumes from a token or ordered key Risk: pages shift when the source changes Risk: invalid or ambiguous cursor semantics When to use which:
- Use offsets for small, stable result sets when the source supports them efficiently and changes during extraction cannot invalidate page boundaries.
- Use cursors for large or changing feeds, preserving the source-provided token exactly or using a unique deterministic key order for keyset pagination.
- Use a consistent snapshot or documented export protocol when the whole extract must represent one point in time rather than a moving collection.
A cursor does not automatically provide snapshot consistency. Confirm ordering, token expiry, update behavior, and whether replaying a page returns the same records.
Q52.How would you build a reliable incremental ingestion pipeline from a paginated API?
I would treat each extraction as a resumable sequence with explicit boundaries, durable progress, and duplicate-safe target writes. API availability and pagination behavior are part of the data contract.
- Confirm authentication scope, rate limits, ordering, update filters, deletion signals, pagination consistency, and the validity period of continuation tokens.
- Request bounded pages using stable filters, validate each response, and retain source identifiers and extraction metadata before transformation.
- Retry transient errors with bounded backoff and server guidance, while stopping or escalating permanent authorization and validation failures.
- Commit page data durably before advancing progress, then reconcile coverage and handle expired cursors or missed history through a defined recovery procedure.
flowchart TD A["Load extraction boundary and cursor"] B["Request next page"] C{"Response valid?"} D["Commit page data"] E{"More pages?"} F["Reconcile and close interval"] G["Classify failure and retry or stop"] A --> B B --> C C -->|yes| D C -->|no| G D --> E E -->|yes| B E -->|no| FTrade-offs:
- Larger pages reduce request overhead but increase memory use and repeated work after a failed page.
- A successful response code does not prove completeness if the API silently truncates history or changes pagination semantics.
Example
A request times out after a page has already reached the destination.
- Resume from the last durably recorded cursor.
- Re-read the uncertain page when necessary.
- Merge by stable source identifiers so replay does not duplicate records.
- Advance the cursor only after confirming that the complete page is durable.
Q53.How should deletes and tombstones propagate through a data platform?
A deletion signal must travel through every relevant derived representation. A tombstone is a marker that identifies a deleted record; its exact encoding and retention depend on the source protocol.
- Identity and order: associate the delete with a stable key and source position so an older replayed update cannot incorrectly resurrect the record.
- Target policy: choose between physical removal, a soft-delete flag, or retained history according to the dataset’s purpose and retention requirements.
- Propagation: update analytical tables, aggregates, indexes, and caches whose contents or totals depend on the removed record.
- Recovery: retain deletion evidence for the required replay horizon, and ensure historical reprocessing applies the same deletion policy before publishing results.
Distinguish a business cancellation from a privacy-driven erasure. They can require different treatment of identifiers, history, backups, and derived measures.
Q54.How would you handle timestamps, timezones, and daylight-saving changes?
I would distinguish an absolute instant from a local business date and preserve enough source context to interpret both. These are different data types conceptually, even when represented as strings.
- Canonical instant: normalize known instants to a consistent reference such as UTC, retaining the original offset or timezone identifier when business interpretation requires it.
- Local meaning: calculate reporting dates using the agreed business timezone rather than the server’s local clock or a fixed offset that changes seasonally.
- Ambiguity: detect local times that occur twice or do not occur during clock changes, and require a source rule instead of guessing silently.
- Precision: preserve sufficient fractional seconds and define interval boundaries consistently, usually including the start and excluding the end.
Do not label an offset-free timestamp as UTC without evidence about how the producer generated it.
Example
An event occurs at 2026-01-01 00:15:00 with offset +05:30.
- Subtract five hours and thirty minutes to obtain 2025-12-31 18:45:00 UTC.
- Retain the source offset or business timezone context.
- A UTC daily report assigns the event to December 31.
- A report using the source business date assigns it to January 1.
Q55.How do row-oriented and column-oriented storage differ?
Row-oriented storage keeps a record’s fields close together. Column-oriented storage groups values from the same column, favoring scans that read a subset of fields across many records.
Row-oriented Column-oriented Reads individual complete records Reads selected columns across many rows Compresses across record layouts Compresses similar adjacent values Fits transactional access Fits analytical scans When to use which:
- Use row-oriented layouts when workloads frequently fetch or update individual records and need many fields from each selected row.
- Use column-oriented layouts when queries aggregate large datasets but read relatively few columns, allowing less input and effective value encoding.
- Evaluate mixed workloads using actual read and write patterns, including update frequency, batch size, indexing, and maintenance behavior.
The storage orientation is not the only determinant of performance. Partitioning, compression, statistics, caching, and query planning can outweigh a simplistic row-versus-column comparison.
Q56.How would you choose between CSV, JSON, and binary data file formats?
I would choose a file representation based on structure, interoperability, scan patterns, and schema requirements. Human readability is useful but can impose parsing and storage costs at scale.
CSV JSON Row-oriented binary Columnar binary Simple tabular exchange Nested and varying records Typed record serialization Analytical scans and compression Weak typing, no nested structure Repeated field names and parsing cost Less selective column reading Small updates need table management When to use which:
- Use CSV for simple exchange when delimiter, quoting, encoding, header, and type-conversion rules are explicitly agreed between producer and consumer.
- Use JSON when retaining nested structure or flexible message attributes matters, while validating the actual schema instead of accepting arbitrary drift.
- Use typed binary formats for sustained processing when schema support, compact storage, efficient reads, and compatible readers justify the additional tooling.
A file format is not a transactional table system. Concurrent updates, snapshots, deletes, and metadata commits need an additional management layer.
Q57.How do partitioning, bucketing, and clustering improve data access differently?
These techniques organize data so a query can avoid work or distribute it more effectively. Their exact behavior and terminology vary by storage and execution engine.
Partitioning Bucketing Clustering Separates data by values or ranges Assigns keys to hash buckets Groups nearby values physically Lets queries skip irrelevant partitions Balances data or supports compatible joins Improves skipping and locality When to use which:
- Use partitions around common selective filters and manageable cardinality, such as business date, while avoiding millions of tiny partitions.
- Use bucketing when supported hash layouts fit join or distribution needs; compatible bucket definitions and engine behavior determine whether shuffles can be avoided.
- Use clustering or sorting when queries repeatedly filter ranges or related keys and storage statistics can exploit the resulting locality.
Evaluate maintenance costs and changing access patterns. A layout optimized for one query can create skew, expensive writes, or poor pruning for another.
Q58.Why do many small files hurt analytical pipelines, and how does compaction help?
Small files can make metadata, file-open, scheduling, and request overhead dominate useful data processing. Compaction combines them into larger files suited to the workload.
- Reading cost: each file may require listing, metadata inspection, planning, and a separate read request even when it contains very few records.
- Write causes: overly frequent micro-batches, excessive partitions, and uncoordinated writers can create a large file count despite modest total data volume.
- Compaction design: combine files within appropriate partitions while preserving records, schema, ordering requirements, and a consistent published table snapshot.
- Operational balance: choose target sizes using query parallelism and storage characteristics, and coordinate compaction with retention and concurrent writes.
One enormous file is not automatically better because it can reduce parallelism or increase rewrite cost. Measure file count, scan efficiency, and maintenance overhead together.
Q59.What are predicate pushdown and projection pushdown?
Predicate pushdown moves supported filtering closer to the data source. Projection pushdown reads only required columns, reducing the data that enters later processing stages.
- Filtering: a source may evaluate a predicate directly or use file and row-group statistics to skip regions that cannot contain matching records.
- Column selection: selecting only needed fields can reduce input substantially in column-oriented storage, while row-oriented sources may offer a different benefit.
- Limitations: unsupported expressions, conversions, complex functions, or missing statistics can prevent a filter from being pushed down or used for skipping.
- Verification: inspect the physical plan and actual bytes or records read rather than assuming an early-looking filter reduced source work.
Pushdown must preserve the query’s meaning, including NULL behavior, type conversions, and timezone interpretation. A logically early filter is not necessarily a physically efficient one.
Q60.How does a distributed engine turn lazy transformations into executable work?
Lazy transformations describe the intended computation without immediately processing the entire dataset. An action or write triggers planning and execution of the required work.
- Build a logical plan describing reads, filters, projections, joins, and aggregations, preserving expressions the optimizer can reason about.
- Optimize that plan using supported rules and statistics, then choose physical operators and data-exchange requirements.
- Divide execution around exchange boundaries into stages and tasks that process partitions across available workers.
- Schedule tasks, move required data, recover failed work according to the engine’s guarantees, and commit or return the completed result.
Laziness allows optimizations such as removing unused columns, but it also means an error may appear only when execution starts. Repeated actions can recompute shared work unless an appropriate result is persisted.
flowchart TD A["Build logical transformations"] B["Action requests result"] C["Optimize physical plan"] D{"Data exchange required?"} E["Create exchange boundary"] F["Schedule partition tasks"] G["Return or commit result"] A --> B B --> C C --> D D -->|yes| E D -->|no| F E --> F F --> G