Data engineer interview questions by company, deduplicated and answered
What 29 companies reportedly asked data engineers, collected from public interview-experience posts, merged into one list of unique questions grouped by topic, with what a strong answer has to cover.
- How the questions were collected
- What each company focuses on
- What comes up most
- SQL
- Python and coding
- Spark architecture and execution
- Partitioning, shuffle and joins
- Data skew
- Memory and caching
- Performance and troubleshooting
- Streaming and Kafka
- Lakehouse and table formats
- Data modeling and warehousing
- Pipeline design and reliability
- Cloud services
- Behavioural and managerial rounds
- How to prepare from this list
- References
- Trademarks
TL;DR
- Interview-experience posts from 29 companies, from Amazon and Netflix to the large IT services firms, collapse into 75 question groups once duplicates and near-duplicates are merged. Window functions came up at 19 of the 29; duplicates and idempotent reloads, slow-job investigations and late-arriving data at 12 or 13 each.
- Product companies (Amazon, Netflix, Atlassian, Grab, Paytm) spend their rounds on system design and failure scenarios. Services and consulting firms (TCS, Infosys, Cognizant, PwC, KPMG, Deloitte) spend theirs on Azure Data Factory, Databricks and SCD implementation, plus a managerial round.
- Treat company labels as hints, not facts. The same question list is posted under different company names, and some posts are verbatim copies across accounts. The questions are real interview material; which company asked a given question cannot be verified.
- Every technical question has a collapsed answer outline: the mechanism, the trap and the follow-up you should expect. Click a question to open it.
A list of “questions asked at company X” is only useful if it tells you what the interviewer is testing. Most of the posts these questions came from do not: they give a question title and move on, and the same thirty titles repeat under a different company name every week.
This post does the merging. It takes the questions from public LinkedIn interview-experience posts for data engineer roles, removes duplicates and near-duplicates, rewrites each one as a precise question, and groups them by the skill they test. Each technical question then gets an outline of what a strong answer covers, written the way the Spark interview questions post does it: the mechanism first, then the trap.
How the questions were collected
The source set is public LinkedIn posts from October 2026 that describe a data engineer interview at a named company, found through LinkedIn content search for “data engineer interview experience” and “interview experience PySpark SQL round”. Only posts that listed concrete questions were kept. Posts that described a process without questions, and posts for other roles (UX designer, GenAI engineer), were dropped.
Three things about this source are worth knowing before you use it:
The company attribution is weak. One twelve-question banking list appears word for word under Wipro, American Express and Databricks. One American Express post appears from four different accounts, one PayPal post from three, and one Cognizant post from three. Many of the posting accounts sell interview kits. Read a company label as “this question set circulated with this name on it”, not as a transcript.
The questions are still representative. The same question reaching you from five accounts says nothing about one company, but it says a lot about the market. The frequency counts below are the most reliable signal in the set.
Compensation figures were left out. The posts quote CTC ranges, but none can be checked, and they are not what you prepare against.
public posts ──► keep posts that list questions ──► normalise wording
│
┌──────────────────────────────────────────┘
▼
merge duplicates and near-duplicates ──► tag each question with
│ the companies it came from
▼
group by skill ──► outline what a strong answer covers
What each company focuses on
The table summarises the reported rounds for each company and the question that best captures what it tests. Companies are grouped by type, because the type predicts the interview better than the name does.
Product and platform companies
| Company | Reported rounds | Focus | Signature question |
|---|---|---|---|
| Amazon | Online assessment, technical deep dive, system design, bar raiser | Scale, cost, idempotency, leadership principles | 50 billion small files in S3 and queries slowing daily: give a remediation plan with no downtime |
| Microsoft | Coding (Python, SQL), Spark, end-to-end system design | SQL depth (self-join, recursive CTE), schema drift, SCD | Handle schema drift in a batch pipeline without breaking downstream tables |
| Netflix | SQL and modeling, PySpark, system design, production scenarios | Event data at scale, Iceberg table management | One task takes 45 minutes while the rest finish in 3. Why? |
| Atlassian | DSA, SQL, data system design, behavioural | Algorithms plus streaming design | Merge overlapping intervals, then design a real-time analytics pipeline with exactly-once semantics |
| Grab | SQL, Spark internals, project deep dive, design | Ride-sharing data model, small files in streaming | Small-file build-up in a high-throughput Kafka-fed pipeline |
| Walmart | SQL, Spark, DSA, project discussion | Consecutive-day patterns, migration, reconciliation | Daily sales reports are wrong after a deployment. Investigate. |
| Comcast | SQL, Spark, streaming | Partitioning, event time, freshness | Find customers whose monthly usage rose three months in a row |
| Ford | Pipeline design, Spark, data quality | Vehicle and sensor data, SCD Type 2 | Process millions of real-time vehicle sensor events |
Fintech and banking
| Company | Reported rounds | Focus | Signature question |
|---|---|---|---|
| Goldman Sachs | Modeling and SQL, big data, platform design, production and leadership | Trade data, table formats, lineage | Delta Lake vs Hudi vs Iceberg for a financial data lake |
| American Express | SQL and Python, Spark, architecture, HR | Recursive SQL, Spark memory, cost vs SLA | Optimise Spark cluster cost while holding the SLA |
| PayPal | Intro, SQL and Python, coding, design, behavioural | Payment ETL, late data, warehouse design | Design an ETL pipeline for payment transactions |
| Paytm | Design-heavy | Exactly-once, Kafka, fraud | Achieve exactly-once processing for payment events |
| HDFC Bank | ADF, Spark tuning, Delta scenario, SQL | Incremental snapshot design | Distinct phone numbers over 90 or 180 days of daily snapshots without scanning them all |
Data and analytics vendors
| Company | Reported rounds | Focus | Signature question |
|---|---|---|---|
| Databricks | Delta Lake, streaming, governance | Delta internals, Unity Catalog, multi-tenancy | A multi-terabyte Delta table has slowed down. Optimise it. |
| IBM | Coding, SQL, project | Window functions, Spark, Kafka basics | Second-highest salary without a subquery |
| Tiger Analytics | SQL, design, behavioural | Fundamentals, late data | Handle late-arriving data in pipelines |
| HCA Healthcare | SQL and PySpark, GCP architecture, debugging | Medallion on GCP, Airflow | Upstream data has not arrived while the DAG is running. What happens? |
Consulting and IT services
| Company | Reported rounds | Focus | Signature question |
|---|---|---|---|
| PwC | SQL and Python, ADF and Databricks, managerial | ADF runtime, MERGE, modeling | Azure IR vs self-hosted IR |
| EY | Spark, ADF, SQL | Retries, incremental loads | A pipeline fails halfway. Retry without duplicating data. |
| KPMG | SQL and Python, ADF and Databricks, managerial | ETL fundamentals, PySpark operations | Join two large datasets that run out of memory |
| Deloitte | Technical, case study, managerial | Migration, GDPR, lineage | Migrate 500 TB of banking history from Oracle to Synapse with zero downtime |
| Wipro | Banking-domain design | Compliance reporting, CDC, audit | Inconsistent balances in a regulatory report. Investigate. |
| Infosys | Technical, ADF and Delta, managerial | End-to-end pipeline explanation | repartition() vs coalesce() vs repartitionByRange() |
| TCS | Technical, technical and managerial, HR | Reusable ETL, banking pipelines | Design a reusable ETL framework for 20 clients with different schemas |
| Cognizant | Technical, Azure, managerial, HR | Azure end to end, cost | Databricks cluster cost doubled this month. Where do you start? |
| HCLTech | Advanced Spark, Delta and Azure | AQE, Delta internals, IaC | Row-level deletes in Delta without rewriting the partition |
| Capgemini | Technical, client technical | GCP plus Databricks | Penultimate order for every customer |
| Coforge | SQL and Python, PySpark and Databricks, client design | SCD2 with MERGE, idempotency | An ADF pipeline loads twice after a retry. Make it idempotent. |
| EPAM | Technical | ADF, Spark joins, Unity Catalog | Incremental load with no primary key and no timestamp |
What comes up most
Counting how many of the 29 companies each topic appeared under gives the clearest picture of where to spend preparation time. The counts come from the company tags on the questions below, so they are lower bounds: a post that only named a topic (“Spark optimisation”) without a question is not counted.
| Topic | Companies | Typical form |
|---|---|---|
| Window functions (rank, running totals, latest row) | 19 | Write it, then explain the tie behaviour |
| Duplicates and idempotent reloads | 13 | “The job ran twice” or “the source resent records” |
| Slow job investigation | 13 | “It used to take 2 hours, now 8” |
| Late-arriving data | 12 | Already-aggregated tables, reports |
| Data skew and salting | 10 | Diagnose from the Spark UI, then fix |
| SCD Type 2 | 10 | Implement with MERGE or in PySpark |
| Incremental load and CDC | 8 | Watermarks, MERGE |
| Delta Lake ACID and maintenance | 8 | Transaction log, OPTIMIZE, VACUUM |
| Schema evolution and drift | 6 | Without breaking downstream consumers |
repartition vs coalesce |
6 | Plus when each is wrong |
The pattern is clear: correctness under failure matters more than API recall. Duplicates, retries, late data and schema change make up most of the scenario questions, and they are all versions of one question: what happens to the data when something goes wrong.
SQL
Each question lists the companies it was reported under in brackets.
1. Find the Nth highest salary, overall and per department, using more than one approach. [PwC, PayPal, Atlassian, IBM, Infosys, TCS, Capgemini, HCA Healthcare]
Expect to give three approaches and say when each one breaks.
DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) = Nis the default. It treats ties correctly, so the “second highest” is the second distinct value.- A correlated subquery,
WHERE N - 1 = (SELECT COUNT(DISTINCT salary) FROM emp e2 WHERE e2.salary > e1.salary AND e2.dept = e1.dept), works without window functions. It is quadratic per group, so say so. ORDER BY salary DESC LIMIT 1 OFFSET N-1overSELECT DISTINCT salaryis fine for the overall case and awkward per department.
The trap: ROW_NUMBER() returns a wrong answer when two people share the
top salary, because it gives them ranks 1 and 2. The “without RANK or a
subquery” variant (TCS, IBM) wants a self-join:
MAX(e1.salary) where a strictly greater e2.salary exists.
2. ROW_NUMBER vs RANK vs DENSE_RANK, and when can a ROW_NUMBER solution be rewritten with DENSE_RANK? [PwC, EY, Walmart, Atlassian, Capgemini, IBM]
For the values 100, 100, 90:
| Function | Result | Use it for |
|---|---|---|
ROW_NUMBER() |
1, 2, 3 | Exactly one row per group (deduplication, latest record) |
RANK() |
1, 1, 3 | Competition ranking with gaps |
DENSE_RANK() |
1, 1, 2 | Nth distinct value |
They agree only when the ORDER BY key is unique within the partition. Once
there are ties, a DENSE_RANK() = 1 filter returns several rows per group
where ROW_NUMBER() = 1 returns one.
The follow-up is determinism. ROW_NUMBER() over a non-unique sort key picks
an arbitrary row among the ties, and in Spark that choice can change between
runs. Add a tiebreaker column.
3. Find duplicate records, delete them, and keep only the latest record per business key. [PwC, EY, Microsoft, PayPal, Tiger Analytics, Ford, HCA Healthcare]
Find: GROUP BY key HAVING COUNT(*) > 1.
Keep the latest:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY business_key
ORDER BY updated_at DESC, ingest_id DESC) AS rn
FROM src) t
WHERE rn = 1;
Delete in place depends on the engine. In SQL Server, a CTE with ROW_NUMBER()
and DELETE ... WHERE rn > 1 works. In Delta or Iceberg, write the
deduplicated result with MERGE or INSERT OVERWRITE rather than issuing
row-by-row deletes.
The follow-up: an exact duplicate (every column equal) and a key duplicate
(same key, different values) are different problems. The first is a
DISTINCT. The second needs a rule for which version wins, and that rule
belongs to the business, not to you.
4. Running totals: claim amount per policy, account balance per transaction, sales per day. [Coforge, Wipro, American Express, Databricks, Microsoft, PayPal, Atlassian]
SUM(amount) OVER (PARTITION BY account_id ORDER BY txn_ts ROWS BETWEEN
UNBOUNDED PRECEDING AND CURRENT ROW).
State the frame explicitly. With an ORDER BY and no frame, the default
is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. That includes every
peer row with the same txn_ts, so two transactions in the same second both
show the combined total. ROWS gives a true row-by-row balance.
For a balance, debits must be negative before the sum. Say that you would check the sign convention in the source.
5. Consecutive patterns: orders on consecutive days, usage rising three months in a row, a value appearing three times in a row. [Walmart, Comcast, American Express]
Two standard techniques:
- LAG/LEAD comparison. For “three rising months”, compare
usagewithLAG(usage, 1)andLAG(usage, 2)in the same row. - Gaps and islands.
date - ROW_NUMBER() OVER (PARTITION BY user ORDER BY date)is constant across a run of consecutive dates. Group by that difference and keep groups withCOUNT(*) >= k.
Gaps and islands generalises to any run length. LAG needs one comparison per
step. Deduplicate dates first: two orders on the same day break the
ROW_NUMBER() arithmetic.
6. Anti-joins: customers who ordered in January but not February at 100M rows, customers with no transaction in 90 days, LEFT SEMI vs LEFT ANTI, and missing records without a LEFT JOIN. [Cognizant, Wipro, American Express, EPAM]
NOT EXISTS or a LEFT ANTI JOIN is the correct shape. NOT IN is the trap:
if the subquery returns a single NULL, x NOT IN (...) is never true and the
query returns zero rows.
LEFT SEMI JOIN returns left rows that have a match, with no right-hand
columns and no duplication when the right side has several matches.
LEFT ANTI JOIN returns left rows with no match.
At 100M rows in Spark, both are hash or sort-merge joins on the key. Prune the
right side to distinct keys for February before the join, and partition by
month so January and February are each a single scan. EXCEPT on the key
columns also works, at the cost of a full deduplication.
7. Second most recent login for every user, or the penultimate order for every customer. [PwC, Capgemini]
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_ts DESC) = 2.
Expect the follow-up: what about a user with only one login? This query drops them. If the requirement is “one row per user, null when there is no second”, left join the result back to the distinct users.
8. Traverse a hierarchy (employees to managers, components to leaf parts) with a recursive CTE. [Microsoft, American Express]
WITH RECURSIVE chain AS (
SELECT emp_id, manager_id, 1 AS depth FROM emp WHERE manager_id IS NULL
UNION ALL
SELECT e.emp_id, e.manager_id, c.depth + 1
FROM emp e JOIN chain c ON e.manager_id = c.emp_id)
SELECT * FROM chain;
Name the two failure modes: a cycle in the data recurses forever, so cap the
depth or track visited ids, and the recursion cost grows with depth. Leaf
nodes are rows whose id never appears as a parent: an anti-join on
manager_id.
Spark 3.5 does not support WITH RECURSIVE. There, the usual answer is an
iterative self-join loop in the driver that stops when an iteration adds no
new rows.
9. List currently active accounts from an accounts table and a status-audit table, where accounts with no audit record count as active. [HDFC Bank]
Take the latest audit row per account with ROW_NUMBER(), left join it to
accounts, and keep rows where COALESCE(latest_status, 'ACTIVE') = 'ACTIVE'.
The test is whether you notice that an inner join silently drops accounts that were never audited, which is the “count as active” clause.
10. Top 3 salaries per department, or top 3 products per region. [KPMG, Microsoft, Infosys]
DENSE_RANK() <= 3 if ties should all be returned, ROW_NUMBER() <= 3 if
exactly three rows are required. Ask which. In PySpark the same logic is
Window.partitionBy("region").orderBy(F.desc("sales")) with F.dense_rank().
11. A query that ran in 2 minutes now takes 20, or a query over billions of rows with several large joins needs optimising. [EY, Walmart, Comcast, PwC, KPMG, PayPal, EPAM, Ford]
Work from evidence, in this order:
- Compare the plans. Get the execution plan now and, if possible, from when it was fast. A changed join strategy or a lost index or partition filter explains most regressions.
- Check what changed. Data volume, statistics (stale statistics lead to bad join orders), a new predicate that stopped partition pruning, a function wrapped around a filter column.
- Reduce the bytes read. Partition and cluster on filter columns, select only needed columns, push filters below joins.
- Fix the joins. Pre-aggregate before joining, filter early, broadcast the small side, check for row explosion from many-to-many keys.
The “it used to be fast” framing is deliberate. The interviewer wants to hear that you start with the plan diff, not with adding indexes.
12. NULL semantics: in aggregates, joins and filters, and what happens with a = null, b = null, a == b? [Comcast, PayPal, Tiger Analytics, KPMG]
- Comparison:
NULL = NULLisNULL, not true, so a filter drops the row. UseIS NULL, Spark’s null-safe<=>, oreqNullSafein PySpark. - Joins: null keys never match in an equi-join. Two rows with a null
customer_iddo not join to each other. - Aggregates:
COUNT(col)andAVG(col)skip nulls, whileCOUNT(*)counts every row. An average that “drops” rows is usually this. - Grouping:
GROUP BYputs all nulls into one group.
13. SQL fundamentals asked as quick checks: CTE vs subquery, GROUP BY vs HAVING, TRUNCATE vs DELETE, indexing, materialized views. [KPMG, Tiger Analytics, PayPal, Capgemini]
| Pair | The answer in one line |
|---|---|
| CTE vs subquery | Same plan in most engines; a CTE is readable and can be referenced twice, but is not automatically materialised |
| WHERE vs HAVING | WHERE filters rows before grouping, HAVING filters groups after |
| TRUNCATE vs DELETE | TRUNCATE deallocates all data with minimal logging and no WHERE; DELETE removes rows and can be filtered |
| Index | A sorted structure that turns a scan into a seek; costs write throughput and storage |
| Materialized view | A stored query result, refreshed on a schedule or incrementally; trades freshness for read cost |
On a lakehouse, the index question usually becomes partitioning, clustering and file-level statistics, because Parquet tables have no B-tree indexes.
14. Find customers whose purchases in the last 90 days exceed their average monthly purchase by more than 50%. [Deloitte]
Two aggregates at different grains, joined on customer: total over the last
90 days, and average of monthly totals over a baseline period. Then filter on
recent_90d > 1.5 * avg_month * 3, or compare per-month rates.
The question is testing whether you define the baseline before writing SQL.
“Average monthly purchase” over which months, and including months with zero
purchases? Months with no rows do not exist in a GROUP BY, so the average
is overstated unless you generate a month calendar.
Python and coding
These rounds are about clean, correct code under pressure, not about algorithms rarely seen in data engineering.
15. Data-shaped Python: deduplicate a list keeping order, count frequencies, find duplicate employees by ID, group consecutive numbers into ranges. [PwC, EY, Azure-role interviews]
- Order-preserving dedupe:
list(dict.fromkeys(items)), since dicts keep insertion order. Aseenset with a loop is the explicit version. - Frequency:
collections.Counter(items). - Duplicates by key: group into a
defaultdict(list)keyed by ID, keep groups with more than one record. - Consecutive ranges: sort, then start a new range whenever
x != prev + 1.
State the complexity for each: all are O(n) after the O(n log n) sort in the last case.
16. Classic algorithm questions: merge overlapping intervals, longest substring without repeating characters, longest consecutive sequence, first non-repeating character, pairs summing to a target, top K frequent elements. [Atlassian, PwC, Walmart, PayPal, Tiger Analytics]
| Problem | Approach | Complexity |
|---|---|---|
| Merge intervals | Sort by start, extend the last interval while overlapping | O(n log n) |
| Longest substring without repeats | Sliding window with last-seen index map | O(n) |
| Longest consecutive sequence | Set; start counting only from x where x-1 is absent | O(n) |
| First non-repeating character | Counter, then one pass in original order | O(n) |
| Pairs summing to target | Hash set of complements | O(n) |
| Top K frequent | Counter plus heapq.nlargest, or bucket sort |
O(n log k) |
For “first non-repeating element in a stream” (PayPal), the follow-up is memory: an ordered dict of candidates plus a set of seen-twice values.
17. Flatten nested JSON, process a multi-GB CSV without loading it into memory, and compute top routes by revenue without pandas. [Coforge, Microsoft, Tiger Analytics, PwC, KPMG]
- Nested JSON: a recursive function that joins parent keys with a separator, and turns lists into either indexed keys or exploded rows. Decide which with the interviewer, because it changes the row count.
- Large CSV: stream with
csv.readerline by line, orpandas.read_csv(chunksize=...), keeping only aggregates in memory. For anything that needs a sort or join, say you would hand it to Spark or DuckDB. - Top routes without pandas: a
defaultdict(float)of route to revenue, thenheapq.nlargest(3, ...).
18. Python language questions: decorators, multithreading vs multiprocessing, mutable vs immutable objects, exceptions. [American Express, Data QA interviews]
- Decorator: a function that takes a function and returns a wrapped one; use
functools.wrapsto keep the name and docstring. A retry or timing decorator is a good example to give. - Threads vs processes: CPython’s GIL lets only one thread run Python bytecode at a time, so threads help I/O-bound work and processes help CPU-bound work.
- Mutability: lists, dicts and sets are mutable; tuples, strings and frozensets are not. The classic bug is a mutable default argument shared across calls.
Spark architecture and execution
19. What happens, end to end, when a Spark application is submitted? [Grab, Azure-role interviews]
spark-submitlaunches the driver, which creates theSparkSession.- The driver asks the cluster manager (YARN, Kubernetes, standalone) for executors.
- Code builds a logical plan; nothing runs until an action.
- On an action, Catalyst analyses and optimises the plan and picks a physical plan.
- The DAG scheduler cuts the plan into stages at shuffle boundaries.
- The task scheduler sends one task per partition per stage to executors.
- Shuffle files are written at each stage boundary and read by the next stage.
- Results go back to the driver or are written to storage.
The follow-up is always “where does it break?”: driver memory on collect(),
executors at shuffle, and the cluster manager when resources are not granted.
20. Given a sequence (read CSV, repartition(2), filter, select, groupBy, collect), say how many jobs, stages and tasks Spark creates. [Azure-role interviews]
Work it from the shuffles. repartition(2) is one exchange and groupBy is
another, so the action produces three stages: the scan stage (one task per
input split), a stage of 2 tasks after the repartition, and the post-aggregation
stage with spark.sql.shuffle.partitions tasks (200 by default), which AQE
may coalesce to fewer.
Reading a CSV with schema inference adds its own job before any of this, because Spark has to read the file to infer the types. That extra job is the detail the question is designed to catch.
21. Narrow vs wide transformations, transformations vs actions, and lazy evaluation. [Capgemini, Azure-role interviews, HCA Healthcare]
A narrow transformation (filter, select, withColumn) computes each output
partition from one input partition. A wide one (groupBy, join, distinct,
repartition) needs data from many, which forces a shuffle and a stage
boundary.
Transformations only add to the plan; actions (collect, count, write)
trigger execution. Laziness is what lets Catalyst push filters into the scan
and collapse projections before anything runs.
22. RDD vs DataFrame vs Dataset, and SparkContext vs SparkSession. [HCA Healthcare, American Express, Azure-role interviews]
RDDs are opaque objects that Spark cannot optimise. DataFrames carry a schema, so Catalyst can prune columns and push filters, and Tungsten stores rows in a compact binary format. A Dataset is a typed DataFrame in Scala and Java; in Python only the DataFrame exists.
SparkSession (since 2.0) is the entry point for SQL, DataFrames and the
catalog. It wraps a SparkContext, which is the lower-level connection to the
cluster.
23. What is the Catalyst optimizer, and what is predicate pushdown? [Grab, Comcast, Azure-role interviews]
Catalyst turns a query into a parsed plan, resolves it against the catalog (analysed plan), applies rule-based rewrites (optimised logical plan), then picks a physical plan with strategies and cost estimates. Whole-stage code generation then compiles parts of the physical plan to JVM bytecode.
Predicate pushdown moves filters as close to the data as possible: into the
Parquet reader, where row-group min/max statistics skip data, or into a JDBC
source’s WHERE clause. Show it with df.explain(): PushedFilters in the
scan node.
24. How does Spark decide the number of partitions, and what is a good target partition size? [Comcast, Azure-role interviews]
- File scans: splits are bounded by
spark.sql.files.maxPartitionBytes, 128 MB by default, adjusted byopenCostInBytesso many small files are packed together. File count does not set partition count directly. - Shuffles:
spark.sql.shuffle.partitions, 200 by default, which AQE coalesces towardspark.sql.adaptive.advisoryPartitionSizeInBytes(64 MB). - Explicit:
repartition(n)andcoalesce(n).
A useful target is 100 to 200 MB of input per task. Too small means scheduling overhead dominates; too large means spills and long tasks.
Partitioning, shuffle and joins
25. repartition() vs coalesce() vs repartitionByRange(): what happens internally and when to use each. [EY, Walmart, Infosys, American Express, HDFC Bank, TCS, Azure-role interviews]
| Operation | Shuffle | Result |
|---|---|---|
repartition(n, cols) |
Full | Even, hash-partitioned partitions |
coalesce(n) |
None | Merges partitions on the same executor; can be uneven |
repartitionByRange(n, cols) |
Full, after sampling | Sorted ranges; good before writing sorted output |
The trap: coalesce(1) before a write does not just produce one file. With
no shuffle to separate them, it pulls the upstream stage down to one task, so
the whole computation runs single-threaded. repartition(1) keeps upstream
parallelism and pays for one shuffle instead.
26. How does a broadcast join work, when do you avoid it, and what if neither side is small? [American Express, HCLTech, EPAM, Netflix, Azure-role interviews]
The driver collects the small side, builds a hash relation and sends it to
every executor, so the large side joins locally with no shuffle. Spark picks
it automatically below spark.sql.autoBroadcastJoinThreshold (10 MB by
default), or when you add a broadcast() hint.
Avoid it when the “small” side is large after decompression, because it must fit in driver memory and in every executor. A forced hint on a wrong size estimate is a common source of driver OOM.
When neither side is small: filter and project both sides first, pre-aggregate if possible, bucket both tables on the join key to avoid the shuffle on repeated joins, and let AQE switch strategy at runtime once actual sizes are known.
27. Broadcasting vs bucketing, and partitioning vs bucketing. [KPMG, Azure-role interviews]
Partitioning splits a table into directories by column value, which lets queries skip directories. It suits low-cardinality filter columns like date.
Bucketing hashes a column into a fixed number of files per partition. Two tables bucketed the same way on the join key can sort-merge join with no shuffle. It suits high-cardinality join keys.
Broadcasting is a per-query choice for one small table. Bucketing is a layout choice paid once at write time for repeated large joins.
28. What are bloom filters, and how do they speed up joins? [American Express]
A bloom filter is a compact bit array that answers “definitely not present” or
“possibly present”. Built from the join keys of the smaller side, it lets the
larger side drop rows that cannot match before the shuffle. Spark added a
runtime bloom-filter join optimisation in 3.3, controlled by
spark.sql.optimizer.runtime.bloomFilter.enabled.
Parquet and Delta also use bloom filters on columns, for point lookups on high-cardinality fields that min/max statistics cannot prune.
29. Joining two large datasets runs out of memory. What do you do? [KPMG, Netflix, Azure-role interviews]
Find where it fails before changing anything. An executor OOM during a sort-merge join is usually skew: one key’s rows do not fit in one task. A driver OOM is usually a broadcast that was too large.
Then: remove a forced broadcast hint, filter and project before the join, check for a many-to-many key that multiplies rows, handle skew (AQE or salting), and raise shuffle partitions so each task holds less. Increasing executor memory is the last step, not the first.
Data skew
30. How do you identify data skew in the Spark UI? One task runs 45 minutes while the rest finish in 3. [Netflix, Comcast, Azure-role interviews]
In the stage’s task table, compare the max with the median for duration, shuffle read size and records. A max many times the median, on a stage that follows a shuffle, is skew. Spill on that one task confirms it.
Then find the key: df.groupBy(key).count().orderBy(desc("count")) usually
shows one value, often a null or a default like 0 or UNKNOWN.
31. Fix skew: AQE skew join, salting, and what to do when AQE is disabled or one key holds 60% of the rows. [HCLTech, Coforge, American Express, HDFC Bank, PwC, Ford, HCA Healthcare]
AQE skew join (on by default since Spark 3.2) splits a shuffle partition
that is both 5 times the median (skewedPartitionFactor) and larger than
256 MB (skewedPartitionThresholdInBytes) into smaller pieces, and replicates
the matching partition from the other side. It only acts on sort-merge joins,
and only above those thresholds.
Salting by hand: add a random salt 0..N-1 to the skewed side’s key,
explode the other side’s matching rows N times with the same salt range, join
on (key, salt), then aggregate.
Choosing N (HDFC asked this directly): roughly the hot key’s size divided by the target partition size. Too small leaves the hot partition hot; too large multiplies the other side by N for no benefit.
When one key is 60% of the data, check whether that key should be joined at all. If it is a null or placeholder, filter it out and union it back after the join. That is often the whole fix.
Memory and caching
32. cache() vs persist(): default storage levels, what happens when cached data does not fit, and how to release it. [HCLTech, Cognizant, Azure-role interviews]
cache() is persist() with the default level. For a DataFrame the default
is memory and disk (PySpark shows it as MEMORY_AND_DISK_DESER); for an RDD it
is MEMORY_ONLY. persist(level) lets you choose.
When it does not fit: with a memory-and-disk level, evicted blocks spill to local disk; with memory only, they are dropped and recomputed from lineage when next needed. Cached storage competes with execution memory in the unified pool, so caching too much slows shuffles.
Release with unpersist(). The follow-up: caching is lazy, so nothing is
stored until an action runs over the cached DataFrame.
33. Spark memory management, driver vs executor memory, and why a job hits OOM despite enough cluster resources. [American Express, Netflix, Azure-role interviews]
Executor heap minus 300 MB reserved is split by spark.memory.fraction
(0.6) into a unified pool shared by execution (shuffles, joins, sorts) and
storage (cache). Execution can evict storage; storage cannot evict execution
below spark.memory.storageFraction. Off-heap overhead
(spark.executor.memoryOverhead) covers JVM internals, Python workers and
network buffers.
OOM with ample cluster capacity is a per-task problem: one skewed partition,
an oversized broadcast, collect() on the driver, or Python UDF workers
exceeding overhead, which shows up as a container killed by YARN or Kubernetes
rather than a Java heap error.
Performance and troubleshooting
34. A job that took 2 hours now takes 8 (or 3x or 4x longer). Walk through the investigation. [Wipro, Deloitte, TCS, Databricks, EY, Azure-role interviews]
- What changed? Input volume, code, cluster, configs, upstream schema. Most regressions are a change nobody announced.
- Compare the Spark UI for a good and a bad run, stage by stage. Find the stage whose time grew.
- In that stage, check input size, shuffle size, spill, task time distribution (skew), GC time and failed or retried tasks.
- Check the storage layer: small files accumulating, a partition filter that stopped pruning, a table growing without compaction.
- Fix the cause and verify on comparable data.
Interviewers listen for a hypothesis tested against evidence, not a list of tuning parameters.
35. A Spark job or streaming query gets slower over days or weeks. What do you look at? [Azure-role interviews, Netflix]
Things that grow without bound: the number of small files in the input table, streaming state size (no watermark, so state is never dropped), the checkpoint or metadata log, Delta or Iceberg metadata without maintenance, and an ever-growing lookup table that was once small enough to broadcast.
36. Too many small files: in a PySpark job, a streaming pipeline, or 50 billion files in an S3 lake. [Amazon, Comcast, Grab, HCLTech, Netflix]
Prevent: repartition by the table’s partition columns before writing, use optimised or auto-compacting writes, and give streaming triggers a sensible interval so each micro-batch writes fewer, larger files.
Repair: run compaction (OPTIMIZE in Delta, rewrite_data_files in
Iceberg, clustering in Hudi) partition by partition. Table formats commit the
rewrite atomically, so readers see old or new files and never a mix. That is
how you get “no downtime”.
At 50 billion files, add that listing itself is the bottleneck. Moving to a table format replaces directory listing with a metadata scan, and compaction then runs in batches ordered by query value.
37. How do you size a cluster for 100 GB, optimise a 500 GB CSV, or cut Spark cost while holding the SLA? [Azure-role interviews, TCS, American Express, Cognizant]
Size from partitions: 100 GB at about 128 MB per task is roughly 800 tasks. A few waves of those across executors with 4 to 5 cores each sets the cluster size. Then check shuffle volume, which is often larger than input.
For a 500 GB CSV: give an explicit schema (inference reads the data twice), make sure the file is splittable (gzip is not), and convert to Parquet once if it will be read again.
For cost: autoscaling, spot or preemptible workers for stateless stages, file compaction so fewer tasks run, and removing unnecessary caching. Measure cost per run before and after.
Streaming and Kafka
38. How do you achieve exactly-once processing for payment events? [Paytm, Atlassian, Netflix]
Exactly-once is an end-to-end property, not a setting. In Structured Streaming it needs a replayable source (Kafka offsets), checkpointed progress, and an idempotent or transactional sink. Spark’s own Kafka sink is at-least-once, so writing back to Kafka needs downstream deduplication.
In practice: write to a Delta, Iceberg or Hudi table, whose commits are tied
to the batch ID, or MERGE on the event ID. On the producer side, Kafka’s
idempotent producer and transactions stop duplicates entering the topic.
39. Duplicate events in Kafka or a streaming job writing duplicates to Delta: how do you prevent and resolve them? [Paytm, Databricks, Netflix]
dropDuplicatesWithinWatermark (Spark 3.5+) or dropDuplicates on the event
ID plus event time with a watermark, so state is bounded. Then make the write
idempotent: MERGE on the event ID inside foreachBatch, or Delta’s
txnAppId and txnVersion options so a replayed batch is skipped.
To repair existing duplicates, rewrite the affected partitions with a
ROW_NUMBER() dedupe.
40. Event time vs processing time, out-of-order and late events, and watermarks. [Comcast, Paytm, Amazon, Netflix]
Event time is when it happened; processing time is when Spark saw it. Window aggregations should use event time, or a delayed batch puts events in the wrong window.
A watermark (withWatermark("event_ts", "2 hours")) tells Spark how late data
may arrive. State older than the watermark is dropped, and events later than
it are discarded.
For Amazon’s version (“30% of events arrive 45 minutes late”): either widen the watermark past 45 minutes and pay for the state, or keep a tight watermark for the real-time view and correct with a batch job that re-aggregates late data into the affected windows.
41. Checkpointing in Structured Streaming: what is in it, and what happens if the checkpoint directory is deleted? [HCLTech, Comcast]
The checkpoint holds the offset log (what each batch will read), the commit log (which batches completed) and the state store for stateful operators. Restart reads it to resume exactly where the query stopped.
Delete it and the query starts as new: offsets come from startingOffsets, so
you reprocess or skip data, and all aggregation state is lost. Duplicates in a
non-idempotent sink are the usual result.
42. Kafka consumer lag keeps growing, or a streaming job falls behind at peak. How do you troubleshoot? [Paytm, Netflix, Databricks]
Compare input rate with processing rate in the streaming query progress. If
processing is slower: check for skew across Kafka partitions, too few
partitions for the consumers, slow sinks, and state growth. Spark reads at most
one task per Kafka partition unless minPartitions splits them.
Fixes: more topic partitions, maxOffsetsPerTrigger to bound batch size, a
cheaper sink path, and scaling executors. A lag graph that grows steadily
means capacity; a sawtooth means slow batches.
43. Batch vs micro-batch vs continuous streaming, and how to choose batch or streaming. [Databricks, Ford, PayPal, Tiger Analytics, Atlassian]
Micro-batch (the Structured Streaming default) runs small batches with second-level latency and exactly-once with a suitable sink. Continuous processing targets millisecond latency, but supports only map-like operations with at-least-once guarantees, and is rarely used.
Choose streaming when the consumer acts on data within minutes. Otherwise a
scheduled batch is cheaper and easier to backfill. Many teams run streaming
with availableNow triggers to get streaming semantics at batch cost.
44. Find users who viewed the same product three times in one hour without purchasing. [Amazon]
Aggregate views by (user, product) over a one-hour event-time window, keep
counts of three or more, and anti-join against purchases for the same
(user, product) and window. In streaming, a watermark bounds the state.
Clarify “one hour”: tumbling windows miss three views that straddle a boundary, so a sliding window or a session-style range check is the honest answer.
Lakehouse and table formats
45. How does Delta Lake provide ACID transactions and handle concurrent reads and writes without locks? [Databricks, PwC, Infosys, Cognizant]
Every change is a new JSON commit file in _delta_log, numbered in sequence.
A table version is the result of replaying commits, with Parquet checkpoints
every so often to keep that fast.
Readers pick a version and read exactly its files, so they never see a
partial write. Writers use optimistic concurrency: they write data files, then
try to create the next commit file atomically. If another writer took that
version first, Delta checks whether the two touched conflicting files, and
either retries or fails with a ConcurrentModificationException subclass.
46. Time travel, OPTIMIZE, VACUUM and Z-ordering in Delta. [Databricks, KPMG, Capgemini]
- Time travel:
VERSION AS OForTIMESTAMP AS OFreads an old version, for audits, reproducing a report or undoing a bad write withRESTORE. - OPTIMIZE: compacts small files into larger ones.
- Z-order:
OPTIMIZE ... ZORDER BY (col)co-locates values so file-level statistics skip more files on filters. - VACUUM: deletes files no longer referenced by any version within the retention period, 7 days by default.
The trap: VACUUM below the retention period removes the files time travel needs, and can break long-running readers.
47. A Delta table has grown to several terabytes and reads are slow. Why, and how do you fix it? [Databricks, EPAM]
Check in this order: small files (count files per partition), filters that do not match the partitioning or clustering, stale or missing column statistics, a long transaction log without recent checkpoints, and wide rows read in full.
Fixes are compaction, clustering or Z-ordering on the common filter columns, selecting fewer columns, and moving partitioning off high-cardinality columns.
48. Delete individual rows in Delta without rewriting whole files, and how data skipping differs from SQL indexes. [HCLTech]
Deletion vectors mark deleted rows in a small sidecar file, so a DELETE
touches only metadata, and the rewrite happens later during compaction. Without
them, Delta rewrites every file containing a deleted row (copy-on-write).
Data skipping uses per-file min/max statistics in the transaction log to skip whole files. Unlike a B-tree index it does not locate individual rows; it only works when values are clustered across files, which is why it pairs with Z-ordering.
49. Delta Lake vs Hudi vs Iceberg, and Parquet vs ORC vs Avro. [Goldman Sachs]
| Delta Lake | Apache Hudi | Apache Iceberg | |
|---|---|---|---|
| Metadata | Ordered JSON log with checkpoints | Timeline of instants | Snapshot, manifest list, manifests |
| Strength | Spark and Databricks integration | Upserts, record-level index, incremental pulls | Engine neutrality, hidden partitioning, partition evolution |
| Row updates | Copy-on-write or deletion vectors | Copy-on-write or merge-on-read | Copy-on-write or delete files |
Parquet and ORC are columnar and suit analytics. Avro is row-based with an embedded schema and suits streaming and record exchange. The format choice is about the workload, not a ranking. The open table formats comparison goes further.
50. Auto Loader vs COPY INTO, Medallion architecture, and Unity Catalog. [Coforge, Databricks, EPAM, Capgemini, HCA Healthcare]
- COPY INTO is an idempotent SQL load that skips files it already loaded. It suits thousands of files arriving in batches.
- Auto Loader (
cloudFiles) is a streaming source that discovers new files incrementally, with schema inference and evolution. It suits continuous arrival and millions of files. - Medallion: Bronze keeps raw data for replay, Silver holds cleaned and deduplicated data, Gold holds business aggregates. The point is recoverability: a Silver bug is fixed by reprocessing from Bronze, not by re-pulling the source.
- Unity Catalog: one governance layer for tables, files and models across workspaces, with grants, lineage and audit.
Data modeling and warehousing
51. Implement SCD Type 2 with MERGE or in PySpark, and explain Types 1, 2 and 3. [Coforge, HDFC Bank, Deloitte, Ford, Wipro, Infosys, TCS, Capgemini, Databricks, Microsoft, Azure-role interviews]
Type 1 overwrites, Type 2 keeps history with a new row per change, Type 3 adds a “previous value” column.
Type 2 in one MERGE needs the staged-union trick: the change rows appear
twice, once with the real key (to match and close the current row) and once
with a null merge key (so they fall through to the insert branch):
MERGE INTO dim_customer t
USING (
SELECT s.customer_id AS merge_key, s.* FROM staged s
UNION ALL
SELECT NULL AS merge_key, s.* FROM staged s
JOIN dim_customer d ON s.customer_id = d.customer_id
WHERE d.is_current AND s.address <> d.address) u
ON t.customer_id = u.merge_key AND t.is_current
WHEN MATCHED AND t.address <> u.address THEN
UPDATE SET is_current = false, end_date = u.effective_date
WHEN NOT MATCHED THEN
INSERT (customer_id, address, effective_date, end_date, is_current)
VALUES (u.customer_id, u.address, u.effective_date, NULL, true);
Follow-ups: compare a hash of tracked columns rather than each column, handle
nulls in the comparison (use <=>), and decide what happens to late changes
that arrive out of order.
52. Star vs snowflake schema, normalization vs denormalization, and many-to-many relationships in a star schema. [PwC, KPMG, Tiger Analytics, PayPal, HCLTech]
A star schema has denormalised dimensions joined directly to the fact, which means fewer joins and simple BI queries. A snowflake normalises dimensions into sub-dimensions, which saves storage and keeps hierarchies consistent but costs joins. Lakehouse BI generally favours star.
Many-to-many (an account with several holders) goes through a bridge table between fact and dimension, with a weighting factor if measures must not be double-counted. The data modeling guide covers grain and fact types.
53. Data lake vs warehouse vs mart vs lakehouse, and when to choose an RDBMS, NoSQL, a lake or a warehouse. [Wipro, TCS, PwC, Infosys, Grab, KPMG]
A lake stores raw files of any shape cheaply. A warehouse stores modelled, governed tables for SQL. A mart is a subject-specific slice of the warehouse. A lakehouse puts table formats on lake storage to get warehouse guarantees (ACID, schema, time travel) without copying data into a separate system.
Choose an RDBMS for transactional consistency and point lookups, NoSQL (DynamoDB, Cassandra) for key-value access at high write rates, and a lake or warehouse for scans and aggregation.
54. Design data models: retail sales by product, vendor, location and time; ride-sharing metrics; a real-time analytics model. [Amazon, Grab, Microsoft]
Start with the grain: one row per order line, or per ride. The fact holds measures (quantity, revenue, duration), and dimensions are product, vendor, store, date and customer. Name additive versus non-additive measures. Ratios like average ride duration are computed, not stored.
Then answer the follow-ups the interviewer will ask: which dimensions change (SCD), how to partition the fact (by date), and what changes at a billion rows (clustering on the common filter keys, pre-aggregated rollups).
55. Count distinct phone numbers over the last 90 or 180 days from a 100M-row table snapshotted daily, without scanning everything. [HDFC Bank]
Do not scan 180 full snapshots. Build an incremental table of first-seen and
last-seen dates per phone number, updated daily from the latest snapshot
only. A 90-day count is then a filter on last_seen >= current_date - 90.
If approximate is acceptable, keep a daily HyperLogLog sketch per day and merge 90 of them. Either way, the insight is to change the storage design so the query becomes cheap.
Pipeline design and reliability
56. A pipeline fails halfway, or loads twice after a retry. How do you make it idempotent? [Coforge, EY, Amazon, Netflix, Atlassian, Ford]
Running a step twice must give the same result as running it once:
- Overwrite by partition, not append:
INSERT OVERWRITEthe day you are loading, or Delta’sreplaceWhere. - MERGE on a business key for upserts.
- Commit atomically. Write to a staging location and swap, or rely on the table format’s commit, so a half-finished run leaves nothing visible.
- Track what was processed: a watermark or batch ID table updated in the same transaction as the data.
For “the same financial transaction arrives twice” (Amazon), the key is a natural or producer-assigned transaction ID with a uniqueness check at write.
57. Incremental loading and CDC, including the case with no primary key and no timestamp. [PwC, Ford, Microsoft, Wipro, Infosys, EPAM, Cognizant, KPMG]
With a reliable updated_at, store the high-water mark and pull rows above it,
with a small overlap to catch clock skew. With log-based CDC (Debezium, ADF
CDC, database change feeds), read the change stream with operation types and
apply it with MERGE.
With no key and no timestamp (EPAM), compute a hash of each full row, compare the current extract with the previous one, and treat new hashes as inserts and missing hashes as deletes. It costs a full extract each time, so say that the real fix is asking the source owner for a change column.
58. Late-arriving data in a table that has already been aggregated, or late cancellations in a Gold table. [Cognizant, Coforge, Walmart, Ford, PayPal, Tiger Analytics, Microsoft, Atlassian]
Store data by event date, not load date. Each run re-aggregates every event date touched by newly arrived records, not just “yesterday”, and overwrites those Gold partitions.
Keep a lookback window (for example, recompute the last 7 days every run) when late arrival is routine, and a targeted backfill for rare very late data. For dimensions that arrive after their facts, insert a placeholder dimension row and update it when the real one lands.
59. Handle schema drift and schema evolution without breaking downstream consumers. [Microsoft, Walmart, Ford, HCLTech, PwC, Netflix, Azure-role interviews]
Separate tolerant ingestion from strict consumption. Bronze accepts new columns (schema evolution on write, or keep the raw payload in a string or VARIANT column). Silver and Gold have explicit contracts.
Additive changes (a new nullable column) can flow through automatically. Breaking changes (rename, type narrowing, dropped column) should fail loudly at a validation step and alert, rather than silently produce nulls downstream. Mention a schema registry for streaming sources and data contracts with producers.
60. Data quality and reconciliation: source has 1 million rows, target has 990,000. Find out why. [Data QA interviews, Walmart, Wipro, Databricks, Deloitte, Ford]
Reconcile stage by stage: counts and key sums at extract, Bronze, Silver and Gold. The stage where counts diverge locates the problem. Then check that stage’s filters, join types (an inner join to a dimension with missing keys is the classic loss), deduplication rules, rejected-record outputs and watermark logic.
Identify the missing keys with an anti-join of source against target, and group them by an attribute to find the pattern. For ongoing checks: row-count, null-rate, uniqueness and freshness assertions that fail the pipeline, not just a dashboard.
61. A pipeline succeeds but the business metrics are wrong, or reports changed after a deployment. How do you debug it? [Netflix, Walmart, Wipro, Databricks]
Treat it as a correctness incident. Pin down which metric, since when, and by how much. Diff the output of the previous code version and the new one on the same input. Most such bugs are join fan-out (duplicates multiplying a sum), a filter change, timezone handling at day boundaries, or a changed upstream definition.
Then prevent recurrence with a regression test that compares key metrics on a fixed sample before deploy.
62. Data lineage and audit: track transformations across an eight-stage pipeline. [Wipro, Deloitte, Goldman Sachs, HCA Healthcare]
Capture lineage automatically rather than documenting it: OpenLineage events from Spark and Airflow, or a catalog such as Unity Catalog that records table- and column-level lineage. Add run metadata (job ID, code version, input snapshot IDs) as columns or in an audit table, so any output row can be traced to the run and inputs that produced it.
63. Migrate an on-premise warehouse (Oracle, 500 TB, 10 years of history) to the cloud with minimal or zero downtime. [Deloitte, Walmart, Amazon]
- Bulk-copy history from a consistent snapshot, partitioned by date, and validate each partition with counts and checksums.
- Start CDC from the snapshot point so the target stays current.
- Run both systems in parallel and reconcile key reports daily.
- Cut consumers over in waves, starting with read-only analytics, and keep the old system as a rollback until sign-off.
Mention transfer limits (500 TB over the network may need a physical transfer appliance), type mapping differences, and who signs off on reconciliation.
64. System design: process billions of payment transactions a day, with real-time fraud detection. [Paytm, Databricks, PayPal, Wipro]
Shape the answer around the two consumers. Producers write to Kafka with an
idempotent producer, keyed by account so per-account ordering holds. A
streaming job scores transactions against features held in a low-latency
store, and emits alerts. A separate path lands every event in a lakehouse
table for reporting and model training, with MERGE on the transaction ID.
Cover: partitioning by account, out-of-order events, exactly-once writes, replay from Kafka retention, PII handling, and reconciliation with the core banking ledger.
65. System design: one architecture for real-time order status and hourly analytics at 500 million orders a day. [Amazon, Coforge, Walmart, Ford, Grab, Comcast]
Use a single event log (Kafka or Kinesis) with two consumers. A streaming job maintains current status per order in a key-value store for customer lookups. A second streaming or micro-batch job appends events to a lakehouse table partitioned by event hour, with hourly aggregates built on top.
At about 6,000 orders per second on average, size for peak, not average. Discuss late events, idempotent upserts into the status store, and replaying from the log to rebuild either side.
66. Design a multi-tenant data platform, or a reusable ETL framework for 20 clients with different schemas. [Databricks, TCS, Deloitte]
Make the pipeline metadata-driven: one engine, with per-client configuration for source, schema mapping, rules and schedule stored in tables, not code. Isolate tenants by catalog or schema with separate permissions, and tag compute for cost attribution.
The trade-off to name: a shared framework cuts duplicated code but makes one client’s special case everyone’s risk. Version the framework, and allow plug-in transforms for exceptions.
67. Storage cost is exploding because the same purchase history is read 50 times a day by different jobs. [Amazon]
The problem is repeated computation, not storage. Find the common transformation those 50 jobs perform, materialise it once as a curated table (or materialised view) partitioned and clustered for their access patterns, and point the jobs at it. Then tier cold history to cheaper storage classes.
Back it with numbers: bytes scanned per day before and after.
68. What do you check before calling a pipeline production-ready, and how do you handle a 2 AM failure? [HCA Healthcare, Capgemini, Infosys, KPMG, PwC]
Production-ready means: correct output validated against a source, idempotent reruns, alerts on failure and on lateness, data-quality checks, a documented backfill procedure, least-privilege access, and known cost per run.
For the 2 AM failure: read the error and the failing step, check whether upstream data arrived, check recent changes, rerun safely if the cause was transient, and communicate the impact on downstream SLAs. Write up the root cause afterwards.
Cloud services
Azure
69. Azure IR vs self-hosted IR, integration runtime vs linked service, and Copy Activity vs Data Flows. [PwC, HDFC Bank, HCLTech]
A linked service is connection information (where and how to connect). An integration runtime is the compute that runs the activity. The Azure IR is managed and reaches public or managed-private endpoints. A self-hosted IR is installed on your own machines to reach on-premise or private-network sources. An Azure-SSIS IR runs SSIS packages.
Copy Activity moves data and is billed by data integration units and time. Mapping Data Flows run transformations on a managed Spark cluster, with cluster start-up time and per-core billing, so they cost more for simple copies.
70. An ADF pipeline is stuck in Queued, or fails every Monday at 6 AM but runs fine otherwise. Investigate. [PwC, Cognizant]
Queued usually means it is waiting for capacity: pipeline or activity concurrency limits reached, a self-hosted IR node offline or saturated, or waiting on a dependency.
Monday-only failures point at what is different on Mondays: a larger weekend backlog, a source system maintenance window, a credential or certificate rotated over the weekend, or another job scheduled at the same time competing for the same IR. Compare the Monday run’s inputs and timing with a good Tuesday run.
71. Secrets, masking and row-level security on Azure: Key Vault, dynamic data masking, Synapse RLS, and infrastructure as code. [PwC, HCLTech, Cognizant]
Keep secrets in Key Vault and reference them from linked services and Databricks secret scopes, accessed with managed identities so no credential is in code. Dynamic data masking hides values at query time for unprivileged users. Row-level security uses a predicate function bound to a security policy to filter rows per user or client. Define all of it with Bicep or Terraform so environments are reproducible and reviewed.
72. Azure Databricks vs Synapse, and an end-to-end Blob → ADF → Databricks → Synapse → Power BI pipeline with its failure points. [EY, Cognizant]
Databricks suits Spark engineering, streaming and ML on Delta. Synapse dedicated SQL pools suit a warehouse-first team with T-SQL skills. Many architectures use Databricks to transform and a SQL serving layer for BI.
Failure points by stage: file arrival and partial files (Blob), IR capacity and credentials (ADF), cluster start-up, skew and schema changes (Databricks), load concurrency and statistics (Synapse), and refresh timeouts (Power BI). Each needs its own alert.
GCP
73. BigQuery partitioning vs clustering, cost reduction, and MERGE. [Capgemini, HCA Healthcare, GCP-role interviews]
Partitioning (by date, ingestion time or integer range) prunes whole
partitions and makes cost predictable. Clustering sorts data within partitions
by up to four columns, so filters on them read fewer blocks. Cost is driven
by bytes scanned: select only needed columns, require partition filters, and
use materialised views for repeated aggregates. MERGE in BigQuery follows
standard SQL with WHEN MATCHED and WHEN NOT MATCHED clauses.
74. Airflow and Composer: operators, and what to do when upstream data has not arrived while the DAG is running. [HCA Healthcare, Capgemini, Walmart]
Operators are the task types: they wrap an action (run a query, submit a Dataproc job, call an API) so a DAG is configuration, not custom code. For missing upstream data, use a sensor (in deferrable mode, so it does not hold a worker slot) with a timeout, alert when it times out, and keep downstream tasks from running on partial data. Rerunning must be idempotent.
AWS
75. S3 storage classes, moving data between tiers, and DynamoDB vs RDS. [KPMG, AWS-role interviews]
S3 offers Standard, Intelligent-Tiering, Standard-IA, One Zone-IA and the Glacier classes (Instant Retrieval, Flexible Retrieval, Deep Archive). Lifecycle rules move objects by age automatically. Watch the minimum storage durations and retrieval charges on the infrequent and archive tiers.
DynamoDB is a managed key-value store for predictable single-digit-millisecond access at any scale. RDS is a managed relational database for joins and transactions.
Behavioural and managerial rounds
These came up at nearly every company with a managerial round (PwC, KPMG, Deloitte, Cognizant, TCS, Infosys, Atlassian, Amazon, PayPal). The questions merge into eight:
- Walk through one end-to-end project: design, your decisions, challenges and impact.
- Tell me about a production failure you owned and what you changed afterwards.
- A technical decision you disagreed with. What evidence did you use?
- A time you took ownership beyond your role.
- How you handle conflicting requirements from stakeholders.
- Delivering under a tight deadline: what you cut, and the consequence.
- Explaining a technical problem (for example, data lag) to a non-technical client.
- A teammate’s mistake caused data loss. How do you handle it?
Prepare two or three real stories and adapt them, rather than one answer per question. Use situation, action and result, and put a number in the result. Amazon’s bar raiser will test each story against its leadership principles, so expect “what data did you use” and “what would you do differently” follow-ups.
How to prepare from this list
Start with the frequency table. Window functions, skew, idempotency, late data and incremental loads appear at most companies. Being solid on those five covers most rounds.
Prepare by company type. For product companies, practise designing systems out loud and coding without an IDE. For services and consulting firms, know Azure Data Factory and Databricks operationally, implement SCD Type 2 from memory, and prepare the managerial stories.
Answer scenarios with evidence. For every “it became slow” or “the numbers are wrong” question, the structure is the same: what changed, where you look, what you found, what you fixed, and how you verified it. That structure is what these interviews reward.
Do not memorise answers. Interviewers change one condition (“now the key is null”, “now there is no timestamp”) and watch whether the answer adapts. Every outline above names the mechanism so you can reason from it.
References
- Spark SQL performance tuning for AQE, join strategies and partition settings
- Spark configuration for memory and shuffle defaults
- Structured Streaming programming guide for watermarks, checkpoints and output semantics
- Delta Lake documentation for the transaction log, MERGE, OPTIMIZE and VACUUM
- Top Apache Spark interview questions for 200 Spark questions answered in depth
- Data modeling for data engineers for grain, SCD and fact types
Trademarks
Apache Spark, Apache Kafka, Apache Hudi, Apache Iceberg, Apache Airflow, Apache Parquet, Apache ORC, Apache Avro and Apache are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries. Delta Lake is a trademark of the Linux Foundation. Databricks and Unity Catalog are trademarks of Databricks, Inc. Azure, Synapse and Power BI are trademarks of Microsoft Corporation. BigQuery and Google Cloud are trademarks of Google LLC. Amazon S3, Amazon Kinesis and DynamoDB are trademarks of Amazon.com, Inc. or its affiliates. Company names are used only to identify where questions were reported.
Found this useful?
These posts and tools are free. If one saved you an afternoon, you can buy me a coffee.