Meta Senior Data Engineer Interview Preparation Guide
Meta's Data Engineer interview process for Senior level consists of 7 rounds spanning approximately 4-6 weeks. The process begins with a recruiter screening call, followed by two technical phone screens (SQL and Python), and concludes with four onsite rounds covering data modeling, system design, product analytics, and behavioral fit. Each round is designed to assess technical depth, system thinking, product intuition, and leadership capabilities expected at the Senior level.
Interview Rounds
Recruiter Screening
What to Expect
Initial call with a Meta recruiter to assess cultural fit, motivation, and basic technical background. This 30-minute conversation covers your professional background, interest in Meta, data engineering experience, and high-level technical competencies. The recruiter evaluates your communication skills, enthusiasm for the role, and general suitability for the interview loop. Expect questions about your career progression, why you're interested in data engineering, why Meta specifically, and what aspects of the role appeal to you.
Tips & Advice
Be genuine and specific about why Meta excites you. Go beyond generic answers—mention specific Meta products and discuss the data engineering challenges behind them. Highlight 1-2 relevant projects from your background that showcase depth in data infrastructure or pipeline design. Keep technical discussion at a high level; save deep dives for technical rounds. Show enthusiasm and ask thoughtful questions about the team and role. Prepare a concise 2-3 minute introduction covering: current role, 1-2 key accomplishments in data engineering, and why you're seeking this opportunity.
Focus Topics
Communication Style & Cultural Fit
Demonstrate clear, thoughtful communication. Explain technical concepts concisely without jargon unless necessary. Show intellectual humility, curiosity about different perspectives, and openness to feedback. Meta values collaborative engineers who can work effectively across teams (data scientists, product managers, infrastructure teams, etc.).
Practice Interview
Study Questions
Motivation for Data Engineering
Clearly articulate why you're passionate about data engineering specifically. Discuss what excites you about building data infrastructure, ETL systems, and enabling data-driven decision-making at scale. Connect your motivation to Meta's mission and the specific challenges of handling petabyte-scale data systems.
Practice Interview
Study Questions
Professional Background & Career Progression
Articulate your career journey as a data engineer with 5-12 years of experience. Focus on progression from junior/mid-level to senior responsibilities, demonstrating increasing ownership of complex projects, mentorship of team members, and influence on data architecture decisions. Highlight how you've grown from implementing pipelines to designing scalable data infrastructure.
Practice Interview
Study Questions
Why Meta & Product Knowledge
Demonstrate genuine knowledge of Meta's products (Facebook, Instagram, WhatsApp, Reels, Ads Manager) and articulate specific reasons for wanting to work on data infrastructure at Meta. Discuss scale challenges (billions of users), technical problems you find intellectually stimulating, or specific Meta initiatives that excite you. Show you understand the data engineering requirements of social platforms at Meta's scale.
Practice Interview
Study Questions
Key Project & Technical Achievements
Prepare 2-3 specific examples of significant data engineering projects you've led or significantly contributed to. For each, be ready to discuss: the business problem, your technical solution, technologies used (Spark, Airflow, cloud platforms, etc.), scale of data handled, and measurable impact. Focus on projects demonstrating pipeline design, system architecture, or data infrastructure ownership.
Practice Interview
Study Questions
Technical Phone Screen - SQL
What to Expect
First technical screening call focusing on SQL expertise and analytical thinking. In this 45-50 minute interview, you'll be asked to write SQL queries to solve business problems using shared coding platforms (like CoderPad or similar). Expect 3-4 medium to hard SQL problems that progress in difficulty. Questions typically involve complex joins, window functions, CTEs, aggregations, and data manipulation. You'll need to write correct, optimized SQL and explain your approach. Interviewers assess SQL proficiency, analytical thinking, ability to handle edge cases, and problem-solving approach under time pressure.
Tips & Advice
Start by clarifying requirements and thinking aloud about your approach before coding. Ask questions about edge cases, data volume, and expected output format. Write clean, readable SQL with proper formatting. Optimize for readability first, then performance. Test your queries mentally against edge cases (NULLs, duplicates, zero records). If you get stuck, communicate your thinking and ask for hints—interviewers appreciate your problem-solving process over perfect solutions. Practice writing SQL on actual platforms to get comfortable. For senior level, expect questions combining multiple concepts (window functions + CTEs + joins). Be prepared to explain query execution plans and suggest indexes for optimization.
Focus Topics
Common Table Expressions (CTEs) & Recursive Queries
Write multi-step CTEs (WITH clauses) to break complex problems into manageable steps. Understand recursive CTEs for hierarchical data or iterative problems. Use CTEs for readability and to avoid nested subqueries. For senior level, handle complex recursive scenarios.
Practice Interview
Study Questions
Query Optimization & Performance
Understand basic query execution plans and how databases optimize queries. Know about indexing strategies (B-tree indexes, composite indexes). Recognize inefficient patterns (SELECT * is often suboptimal, cartesian products, unnecessary subqueries). Discuss trade-offs between different query approaches and justify your optimization choices.
Practice Interview
Study Questions
NULL Handling & Edge Cases
Understand NULL semantics in SQL. Use COALESCE, NULLIF, and IS NULL / IS NOT NULL appropriately. Handle edge cases like division by zero, empty result sets, and queries returning different data types. Write robust queries that don't fail or produce incorrect results for unexpected data.
Practice Interview
Study Questions
Advanced SQL Queries & Window Functions
Master window functions (ROW_NUMBER, RANK, DENSE_RANK, LEAD, LAG, SUM OVER, AVG OVER, etc.) for analytical queries. Understand ranking, running totals, and comparing current row with previous/next rows. Be comfortable using PARTITION BY and ORDER BY clauses. For senior level, combine window functions with CTEs and complex joins to solve multi-step analytical problems.
Practice Interview
Study Questions
Complex Joins & Multi-Table Aggregations
Be proficient with INNER, LEFT, RIGHT, FULL OUTER joins and self-joins. Understand how to join multiple tables and aggregate across them correctly. Handle scenarios with duplicate rows, multiple matches, and many-to-many relationships. Know when to use joins vs subqueries and understand performance implications.
Practice Interview
Study Questions
Technical Phone Screen - Python & Coding
What to Expect
Second technical screening call focusing on Python programming and data processing logic. In this 45-50 minute interview, you'll solve 3-4 algorithmic problems using Python on a shared coding platform. Problems range from medium to hard difficulty and often involve data structures (lists, dictionaries, sets), string manipulation, algorithms (sorting, searching, graph traversal), and time/space complexity analysis. Expect problems like finding patterns in data, processing sequences, or simulating data transformations. Interviewers assess coding ability, problem-solving approach, code quality, and ability to think about complexity and edge cases.
Tips & Advice
Think out loud and explain your approach before coding. Ask clarifying questions about input constraints and expected complexity. Start with a correct solution, then optimize if needed. Write clean, readable code with meaningful variable names. Handle edge cases (empty input, single element, duplicates). Discuss time and space complexity explicitly. For senior level, you're expected to write near-perfect code with minimal bugs. Test your solution mentally with examples. If you get stuck, explain your thinking and ask clarifying questions. Be comfortable explaining why you chose a particular data structure or algorithm.
Focus Topics
String Manipulation & Pattern Matching
Work with string operations, searching, splitting, joining, and pattern matching. Understand string immutability and efficient string building. Handle character encoding and case sensitivity. Solve problems like finding mismatched words, checking substrings, and data parsing.
Practice Interview
Study Questions
Edge Cases & Error Handling
Anticipate edge cases: empty input, single element, duplicates, invalid input, and boundary conditions. Write code that handles these gracefully. Understand when to raise exceptions vs return special values. For data processing, handle cases like missing data, type mismatches, and malformed records.
Practice Interview
Study Questions
List Manipulation & Data Transformation
Solve problems involving list operations: finding elements, sorting, filtering, transforming, and computing aggregates. Handle problems like finding monotonic sequences, computing running averages, or extracting specific patterns. Understand list comprehensions and functional approaches for efficient data transformation.
Practice Interview
Study Questions
Algorithm Design & Complexity Analysis
Solve problems using appropriate algorithms: searching (binary search), sorting, recursion, and dynamic programming when applicable. Understand Big O notation and analyze time/space complexity. Choose algorithms with optimal complexity and justify your choices. For hard problems, optimize from initial O(n²) to O(n log n) or O(n) solutions.
Practice Interview
Study Questions
Python Data Structures & Collections
Master Python's built-in data structures: lists, tuples, dictionaries, sets, and deques. Understand their performance characteristics (O(1) vs O(n) operations). Know when to use each: dictionaries for fast lookups, sets for membership testing and deduplication, deques for efficient queue/stack operations. Be comfortable with nested structures and understand immutability implications.
Practice Interview
Study Questions
Onsite Round 1 - Data Modeling & Schema Design
What to Expect
First onsite round focusing on data modeling and schema design for analytics. In this 50-60 minute interview, you'll design data models and schemas to support specific analytics use cases. Expect questions like 'Design a data model for tracking Facebook post interactions' or 'Create a schema for an e-commerce platform'. You'll discuss dimensional modeling (star schema, snowflake schema), fact and dimension tables, normalization vs denormalization trade-offs, partitioning strategies, and query optimization. Expect to draw diagrams, discuss join patterns, and explain how your design supports specific queries. Interviewers assess your data architecture thinking, understanding of analytics patterns, and ability to balance query performance with storage efficiency.
Tips & Advice
Start by asking clarifying questions: What queries need to be supported? What's the data volume and query frequency? What's the latency requirement? Then propose a schema design, explaining your choices. Use dimensional modeling patterns (fact/dimension tables) appropriate for analytics. Discuss normalization vs denormalization—normalization saves storage but denormalization improves query speed. For senior level, consider scalability: how would this design handle 10x data growth? Discuss partitioning strategy (by date, user_id, etc.) and indexing. Draw clear diagrams and explain join patterns. Be ready to justify decisions and consider trade-offs. Mention specific Meta products when discussing scale.
Focus Topics
Indexing for Query Optimization
Understand indexing strategies: single-column indexes, composite indexes, covering indexes, and when to create them. Know the cost of indexes (storage, write performance) vs benefits (read performance). Design indexes supporting key query patterns without excessive overhead. Discuss trade-offs between query speed and insert/update performance.
Practice Interview
Study Questions
Handling Data Quality & Consistency
Design schemas incorporating data quality from the ground up. Include metadata (load timestamps, data quality indicators, row counts). Discuss approaches: NOT NULL constraints, unique constraints, foreign keys. Design change tracking (which user made what change). For senior level, consider data lineage and impact of data quality issues on downstream analytics.
Practice Interview
Study Questions
Normalization vs Denormalization Trade-offs
Understand database normalization (1NF, 2NF, 3NF) and when to denormalize. Discuss trade-offs: normalized schemas reduce storage and ensure data consistency but require more joins; denormalized schemas are faster for reads but duplicate data. Make conscious trade-off decisions based on access patterns and update frequency. For analytics, discuss why denormalization often makes sense.
Practice Interview
Study Questions
Star Schema & Dimensional Modeling
Design star schemas with fact tables (measurable events/transactions) and dimension tables (descriptive attributes). Understand slowly changing dimensions (SCD Type 1, Type 2, Type 3). Know when to use dimension tables vs embedding attributes directly. For senior level, handle complex dimensional hierarchies and slowly changing dimensions in large-scale systems.
Practice Interview
Study Questions
Partitioning & Sharding Strategy
Design partitioning strategies for large tables: partition by date (most common for time-series data), user_id (for user-centric analyses), or other natural segments. Understand sharding for distributed systems and consistent hashing. Discuss benefits (query pruning, parallel processing) and trade-offs (uneven data distribution, query complexity across partitions).
Practice Interview
Study Questions
Onsite Round 2 - System Design & Data Pipeline Architecture
What to Expect
Second onsite round focusing on designing large-scale data pipeline systems. In this 50-60 minute interview, you'll design end-to-end data systems: how to ingest data from sources, transform it, store it, and expose it for consumption. Expect questions like 'Design a data platform to compute engagement metrics for Reels in near real-time' or 'Architect a system that logs and aggregates ad-performance data for downstream consumers'. You'll discuss data ingestion patterns (batch vs streaming), transformation logic, storage layers (data lakes, warehouses), orchestration (Airflow, DAGs), monitoring, and reliability. Expect to draw architecture diagrams and explain technology choices. Interviewers assess your ability to design scalable, reliable systems handling petabyte-scale data.
Tips & Advice
Start with clarifying questions: data volume, latency requirements (batch vs real-time), data sources, and end consumers. Propose a layered architecture: ingestion → transformation → storage → serving. For senior level, discuss scalability, reliability, and operational complexity. Address challenges: how do you handle data quality? Monitor pipeline health? Retry failures? Ensure exactly-once semantics? Discuss technology choices (Spark for batch, Kafka for streaming, Airflow for orchestration, data lakes vs warehouses). Draw clear architecture diagrams showing data flow. Explain trade-offs (complexity vs performance, real-time vs batch). Discuss observability: metrics, logging, alerting. Be ready to deep-dive into specific components.
Focus Topics
Data Lineage & Impact Analysis
Design systems tracking data lineage: which source tables feed which downstream tables? If a source table has bad data, which downstream systems are affected? Implement lineage tracking for debugging and impact analysis. For senior level, comprehensive lineage enabling quick root-cause analysis of data issues.
Practice Interview
Study Questions
Big Data Technologies Stack (Spark, Hadoop, Cloud Platforms)
Understand distributed computing frameworks: Apache Spark (in-memory processing, faster than Hadoop), Hadoop (batch processing at scale). Understand cloud platforms: AWS (S3, RDS, Redshift, Glue), Azure, GCP. Know when to use each technology. Design for scalability across these platforms. For senior level, optimize cluster sizing, resource allocation, and cost.
Practice Interview
Study Questions
Data Quality, Monitoring & Reliability
Design monitoring for data pipelines: check for missing data, late arrivals, duplicate records, schema mismatches, and outliers. Build alerting systems notifying teams of issues. Design recovery mechanisms for pipeline failures. Implement data quality tests (row counts match, no unexpected NULLs, values in valid range). For senior level, comprehensive monitoring and SLA management.
Practice Interview
Study Questions
Data Orchestration & Workflow Management (Airflow DAGs)
Design DAGs (Directed Acyclic Graphs) for orchestrating complex multi-step pipelines. Understand task dependencies, scheduling, monitoring, and retry logic. Use tools like Airflow. Design for fault tolerance: if step 3 fails, how do you recover? Understand incremental loads and checkpoint management. For senior level, manage hundreds or thousands of interdependent jobs.
Practice Interview
Study Questions
Batch vs Streaming Architecture Trade-offs
Understand batch processing (Spark, Hadoop) for high throughput, complete data transformation, and cost efficiency. Understand streaming (Kafka, Flink) for low latency and real-time metrics. Discuss trade-offs: batch is simpler, cheaper, but has higher latency; streaming is complex, more expensive, but real-time. Know when each is appropriate (real-time dashboards vs overnight aggregations).
Practice Interview
Study Questions
ETL Pipeline Architecture & Design Patterns
Design end-to-end ETL systems: Extract (ingestion from sources), Transform (cleaning, aggregation, enrichment), Load (into target systems). Understand common patterns: lambda architecture (batch + streaming), kappa architecture (streaming-only), medallion architecture (bronze/silver/gold layers). For senior level, design pipelines handling petabyte scale and supporting diverse downstream use cases.
Practice Interview
Study Questions
Onsite Round 3 - Product Analytics & Metrics Design
What to Expect
Third onsite round focusing on product analytics, metric definition, and product sense. In this 50-60 minute interview, you'll demonstrate understanding of how data drives product decisions at Meta. Expect questions like 'How would you measure success of a new Instagram Reels feature?' or 'Design a dashboard highlighting Facebook user behavior trends'. You'll define KPIs, discuss dashboard design, identify how to detect anomalies, and think through product tradeoffs. Interviewers assess your ability to think like both an engineer and an analyst—connecting technical data infrastructure to business impact. You'll discuss metrics, dimensional analysis, and how data insights drive product decisions.
Tips & Advice
Demonstrate Meta-specific product knowledge. Ask clarifying questions about the product goal. Think through multiple metrics addressing different aspects of success. Define metrics precisely (e.g., DAU = unique users with at least one action in 24 hours). Discuss why each metric matters. For dashboards, consider: what's the primary question? Who uses it? How frequently? Design for clarity and actionability. For anomaly detection, explain your approach. For senior level, connect to business strategy and discuss trade-offs (engagement vs retention, short-term vs long-term). Show you understand Meta's business (advertising revenue model, user engagement). Discuss how data informs product strategy.
Focus Topics
Experimentation & Causal Inference
Understand A/B testing design: control vs treatment groups, statistical significance, power analysis, minimum detectable effect size. Design experiments measuring feature impact. Understand challenges: network effects (user behavior affects other users), carryover effects, multiple comparisons. For senior level, complex experimental designs and statistical rigor.
Practice Interview
Study Questions
Dashboard Design & Data Visualization for Insights
Design dashboards answering specific business questions. Consider: primary metrics (what's the top line?), secondary metrics (what's driving it?), filters/dimensions (segment by country, device, etc.). Design for different audiences: executives need summaries, product managers need drill-down capability. Discuss update frequency (real-time vs daily). Understand visualization choices (line charts for trends, bar charts for comparisons, etc.).
Practice Interview
Study Questions
Product Understanding & Business Impact Connection
Demonstrate deep understanding of Meta's products and business model. Know how Meta monetizes (advertising), key products (Facebook, Instagram, WhatsApp, Reels), and business metrics (user growth, engagement, ARPU). Connect technical metrics to business outcomes. For senior level, understand strategy trade-offs (user acquisition vs monetization, engagement vs privacy, etc.).
Practice Interview
Study Questions
Metric Definition & KPI Design
Define clear, measurable metrics (KPIs) for product features. Understand different metric types: engagement (DAU, MAU, time spent), monetization (ARPU, total revenue), retention, growth. Define metrics precisely with numerator/denominator clarity. For senior level, design metric hierarchies supporting different stakeholders (executives need high-level metrics, product managers need detailed metrics). Understand lag time and leading indicators.
Practice Interview
Study Questions
Anomaly Detection & Diagnosis
Design approaches to detect metric anomalies: statistical methods (z-score, moving averages, control limits), machine learning approaches, manual review. For anomalies, design diagnostic questions: is it real or a data quality issue? If real, what's causing it? Design drill-down analytics: segment by country, user cohort, traffic source. For senior level, automated anomaly detection and alerting systems.
Practice Interview
Study Questions
Onsite Round 4 - Behavioral & Leadership
What to Expect
Fourth onsite round assessing behavioral fit, leadership capabilities, and cultural alignment. In this 40-50 minute interview, interviewers explore your past experiences through behavioral questions. Expect questions about conflict resolution, cross-functional collaboration, handling ambiguity, mentoring, and how you've influenced decisions. Questions like 'Tell me about a time you had to work with a difficult team member' or 'Describe a decision you made that influenced product strategy'. For senior level, expect focus on leadership: How have you grown as an engineer? How do you mentor others? How do you drive decisions in ambiguous situations? Interviewers assess cultural fit, growth mindset, and ability to work in Meta's collaborative environment.
Tips & Advice
Use the STAR method (Situation, Task, Action, Result) for behavioral questions. Prepare 4-5 stories showcasing different competencies: technical leadership, cross-functional collaboration, handling ambiguity, conflict resolution, mentoring. For each story, emphasize your role and impact. Discuss what you learned. Show growth mindset—talk about mistakes and how you improved. For senior level, emphasize: owning large initiatives end-to-end, mentoring junior engineers, influencing architectural decisions, cross-team collaboration. Show you lift others up. Discuss your philosophy on engineering and leadership. Ask thoughtful questions about team dynamics and growth opportunities. Be authentic; avoid over-rehearsed answers.
Focus Topics
Growth Mindset & Learning from Failures
Share a significant mistake or failure. What did you learn? How did you improve? Show humility and growth. For senior level, discuss how you help teams learn from failures psychologically safely. Emphasize continuous learning despite expertise.
Practice Interview
Study Questions
Conflict Resolution & Difficult Situations
Discuss conflicts you've navigated: technical disagreements, resource conflicts, cross-team issues. How did you approach them? Whose perspective did you consider? Did you change your mind? For senior level, discuss facilitating resolution between teams, not just personal conflicts.
Practice Interview
Study Questions
Handling Ambiguity & Making Decisions with Incomplete Information
Describe situations where requirements were ambiguous or changing. How did you gather information? Make decisions with incomplete data? Adapt? For senior level, discuss leading through ambiguity, helping teams move forward despite uncertainty.
Practice Interview
Study Questions
Mentoring & Developing Others
Describe experiences mentoring junior engineers or colleagues. How did you help them grow? What progress did you see? For senior level, discuss mentoring multiple people, helping them advance their careers. Show genuine interest in growing others. Discuss your mentoring philosophy.
Practice Interview
Study Questions
Cross-Functional Collaboration & Communication
Share experiences collaborating with data scientists, product managers, analytics engineers, infrastructure teams, etc. How did you align different perspectives? Resolve disagreements? Ensure technical decisions served business needs? For senior level, discuss influencing decisions across organizations, not just within your team.
Practice Interview
Study Questions
Ownership & Project Leadership at Senior Level
Demonstrate how you've owned substantial projects end-to-end, from conception to shipping. Discuss a project where you: identified the problem, designed the solution, led the implementation, overcame obstacles, and measured impact. Show accountability for outcomes. For senior level, discuss projects spanning quarters/years and impacting multiple teams.
Practice Interview
Study Questions
Frequently Asked Data Engineer Interview Questions
Describe three strategies to validate a newly implemented metric pipeline that computes 'monthly active subscriptions' after a production deploy. Include manual spot checks, automated tests, and monitoring alerts you would put in place.
Sample Answer
Direct answer: Combine a manual spot check against a small known sample, an automated regression test comparing the new pipeline's output to the legacy value it's replacing, and a monitoring alert on the metric's ongoing volume/distribution after go-live.
Structured elaboration:
- Manual spot check: pick a handful of specific, real users/subscriptions whose subscription status you can verify by hand (e.g., in the billing admin UI) and confirm the new pipeline counts them correctly as active or not; this catches gross logic errors quickly, before investing in the more expensive checks below, and builds confidence the shape of the logic is right.
- Automated regression test: run the new pipeline's
monthly_active_subscriptionsvalue against the OLD pipeline's value (if one existed) or against a hand-computed expectation on a synthetic fixture, for several historical months, and assert the difference is either zero or fully explained by a documented, deliberate logic change (not an accidental discrepancy). - Monitoring alert post-deploy: track the metric's day-over-day and month-over-month values against a documented expected range (e.g., shouldn't jump more than X% without a known cause like a marketing campaign), and separately monitor upstream input volume (row counts from the
subscriptionstable) to catch a silent input-side regression (a broken upstream feed) distinct from a bug in this pipeline's own logic.
Worked example: deploying a new monthly_active_subscriptions pipeline, spot-checking 5 known active subscribers and 5 known-cancelled ones against the new pipeline's output catches an obvious "cancelled subscriptions still counted" bug immediately; running the new pipeline against the last 6 months of historical data and diffing against the old pipeline's stored historical values surfaces any month where the two disagree, which is investigated before the new pipeline becomes the system of record; and a day-1 alert threshold (e.g., flag if today's count differs from yesterday's by more than 5% with no known driver) catches an unexpected regression within a day rather than a stakeholder noticing weeks later.
Trade-offs & pitfalls: Skipping the spot check and going straight to automated regression testing is a common shortcut that misses a bug present in BOTH the old and new pipeline (since a diff-against-legacy check by definition can't catch an error the legacy version shared); the manual spot check against ground truth (the actual billing system, not another pipeline) is what catches that class of shared bug. Conversely, relying only on spot checks without the automated regression test and ongoing monitoring means a LATER regression (introduced by an unrelated future change) goes undetected indefinitely.
Explain FIRST_VALUE, LAST_VALUE, and NTH_VALUE. Then walk through the classic gotcha: given sales(sale_date, store_id, amount), why does LAST_VALUE(amount) OVER (PARTITION BY store_id ORDER BY sale_date) usually just return the current row's amount instead of the partition's true last value, and how do you fix the frame so it returns what you actually want?
Sample Answer
Direct answer
FIRST_VALUE, LAST_VALUE, and NTH_VALUE each return one specific value from the rows currently inside the window frame, not the whole partition. That distinction is exactly why LAST_VALUE(amount) OVER (PARTITION BY store_id ORDER BY sale_date) usually just returns the current row's own amount: with an ORDER BY and no explicit frame, the default frame is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, so "the last row in the frame" is, by construction, the current row itself. The fix is to widen the frame to cover the whole partition: ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.
Structured elaboration
FIRST_VALUE(expr) OVER (...)returns the value from the first row of the current frame.LAST_VALUE(expr) OVER (...)returns the value from the last row of the current frame.NTH_VALUE(expr, n) OVER (...)returns the value from the n-th row (1-indexed) of the current frame.- Why
FIRST_VALUElooks unaffected: the default frame always starts atUNBOUNDED PRECEDING, so "the first row of the frame" is stable no matter where the frame's end boundary sits; only the end boundary (CURRENT ROWby default) moves as you scan down the partition, which is whyLAST_VALUEis the one that changes per row whileFIRST_VALUEdoes not. - Fix:
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGmakes the frame equal to the entire partition for every row, soLAST_VALUE(andNTH_VALUE) become stable, partition-wide values instead of per-row artifacts of where the default frame happened to end. NULLs inside the value column: theIGNORE NULLSclause (LAST_VALUE(amount) IGNORE NULLS OVER (...)) skipsNULLs when locating the target row, and is supported in Snowflake, Oracle, SQL Server (2022 and later, and Azure SQL Database; earlier SQL Server versions do not have it), BigQuery, DuckDB, and Databricks, but PostgreSQL and MySQL do not support it as a window-function clause; on those engines, the portable fallback is a correlated subquery:(SELECT amount FROM sales s2 WHERE s2.id = s.id AND s2.amount IS NOT NULL ORDER BY s2.date DESC LIMIT 1).
Worked example
-- BUGGY: default frame, LAST_VALUE just echoes the current row
SELECT store_id, sale_date, amount,
LAST_VALUE(amount) OVER (PARTITION BY store_id ORDER BY sale_date) AS last_value_buggy
FROM sales;
-- FIXED: widen the frame to the whole partition
SELECT store_id, sale_date, amount,
LAST_VALUE(amount) OVER (PARTITION BY store_id ORDER BY sale_date
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_value_fixed
FROM sales;
Executed against two stores (store 1: amounts 50, 70, 40 on three consecutive days; store 2: amounts 20, 90 on two consecutive days): the buggy version returns 50, 70, 40 for store 1 (each row echoing itself) and 20, 90 for store 2; the fixed version returns 40, 40, 40 for store 1 (the true last amount, repeated on every row) and 90, 90 for store 2. FIRST_VALUE(amount) OVER (PARTITION BY store_id ORDER BY sale_date) (no explicit frame needed) correctly returns 50, 50, 50 and 20, 20 without any modification, confirming it was never affected by the default-frame issue in the first place.
Trade-offs & pitfalls
- Widening the frame to the whole partition changes the query's cost profile:
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROWcan often be evaluated incrementally in one pass over sorted data, whileUNBOUNDED PRECEDING AND UNBOUNDED FOLLOWINGrequires the engine to have the entire partition available before it can emit any row for that partition, which raises memory pressure and spill risk on large partitions. - The same root cause (an implicit frame that ends at
CURRENT ROW) is what makes a running total silently change when theORDER BYcolumn has duplicate values;LAST_VALUE's default-frame bug and that running-total tie behavior are two symptoms of the same underlying rule, not two unrelated gotchas. FIRST_VALUEis not immune to every ordering mistake: if you orderDESCto get "the highest" instead of "the chronologically first," the semantics of whatFIRST_VALUEreturns change completely, so be explicit and deliberate aboutORDER BYdirection, not just about the frame.
Explain what a covering index is and write SQL (SQL Server syntax) to create an index that covers this query:
SELECT product_id, SUM(quantity) AS qty FROM order_items WHERE order_date >= '2025-01-01' GROUP BY product_id;
Explain why your index covers the query and how it reduces IO.
Sample Answer
Direct answer
A covering index includes every column a query needs, either as searchable key columns or as extra "tag-along" data, so the database can answer the query entirely from the index and never has to make a second trip to the table's own storage (an "index-only scan"). In SQL Server T-SQL syntax, the index for this query is:
CREATE INDEX idx_order_items_date_covering
ON order_items (order_date)
INCLUDE (product_id, quantity);
order_date is the key column, since it's what the WHERE clause filters on. product_id and quantity go in INCLUDE rather than the key, because the query never filters or sorts on them, it only needs their values: SQL Server's INCLUDE clause exists specifically to add such non-key payload columns to an index's leaf level without making them part of the sortable key.
Structured elaboration
Why "covers" matters mechanically. Without covering columns, an index on order_date alone would still need a second, separate read per matching row: the index narrows down WHICH rows match, then the database has to go fetch each matching row from the table to retrieve product_id and quantity. That second read is effectively random-access I/O (input/output, meaning it jumps around the table rather than reading sequentially), one per matching row, which adds up fast on a query that matches many rows, like this one likely does over a >= date filter.
Why it reduces I/O specifically. With product_id and quantity carried in the index itself, the database can satisfy the entire query (find matching order_date rows, then read product_id/quantity off the same index entries, aggregate) by touching only the index's own storage. That is strictly less total data read than "index plus table," because the covering index is typically much smaller than the full table (it doesn't need every column, just the ones this query touches).
Key columns versus included columns. Only the key columns are used to search and sort the index; included columns are pure payload, carried at the leaf level. Putting product_id/quantity in INCLUDE rather than in the key keeps the searchable key itself narrow (just order_date), which keeps the index's internal tree shallow and fast to search, while still avoiding the table round-trip for the payload.
Worked example
The T-SQL statement above is the deliverable this question asks for, and its mechanism, "does the extra column carried in the index avoid a second table lookup", is directly demonstrable, verified here against a real engine rather than claimed on faith. On order_items(order_item_id, order_id, product_id, quantity, order_date), 800,000 rows, using Postgres's equivalent INCLUDE syntax to prove the mechanism (the underlying idea, avoiding a second heap/table fetch, is the same one SQL Server's INCLUDE clause exists to provide, even though the two engines are different products with different query planners):
EXPLAIN (ANALYZE, BUFFERS)
SELECT product_id, SUM(quantity) AS qty FROM order_items
WHERE order_date >= '2025-01-01' GROUP BY product_id;
Before any index:
Finalize HashAggregate (actual time=28.471..28.720 rows=5000 loops=1)
-> Gather
-> Partial HashAggregate
-> Parallel Seq Scan on order_items (actual time=0.018..18.333 rows=71606 loops=3)
Filter: (order_date >= '2025-01-01'::date)
Buffers: shared read=5883
Execution Time: 28.917 ms
After CREATE INDEX idx_order_items_date_covering ON order_items (order_date) INCLUDE (product_id, quantity);:
HashAggregate (actual time=30.155..30.406 rows=5000 loops=1)
-> Index Only Scan using idx_order_items_date_covering on order_items (actual time=0.022..10.915 rows=214818 loops=1)
Index Cond: (order_date >= '2025-01-01'::date)
Heap Fetches: 0
Buffers: shared hit=1 read=826
Execution Time: 30.567 ms
Heap Fetches: 0 is the direct, printed confirmation that the covering index worked: every row the query needed came from the index itself, zero trips back to the table. The reliable win here is I/O: buffer reads dropped from 5,883 to 826, roughly an 86% reduction. Wall-clock execution time did not improve in this particular run (28.9 ms versus 30.6 ms), because the uncovered plan happened to parallelize across two workers while the covering-index plan ran as a single serial scan; that is a real, honestly-reported result, not a hidden failure. The I/O reduction is the number to trust here, since it reflects actual work the engine did rather than one run's scheduling noise, and it is the number that will matter more under concurrent load or a cold cache, where every extra table page read competes for shared disk and cache bandwidth.
Trade-offs & pitfalls
A covering index costs more storage than a plain key-only index, since it duplicates the included columns; only include columns the query genuinely needs, not "everything that might be useful someday." If product_id or quantity change frequently, remember they still have to be kept in sync inside this index on every write, same as any indexed column, INCLUDE doesn't make a column free to maintain, it just keeps it out of the sortable key. Don't over-read a single run's wall-clock number as the whole story, as shown above: check the buffer/I/O counts, which are the more reliable signal of whether the covering index is actually doing its job.
Someone you mentor made a mistake that had real, visible consequences for the team or the product. How did you handle the conversation and the follow-up with them?
Sample Answer
Direct answer
The conversation matters less than the sequence: separate stabilizing the consequence from the coaching conversation, then run the retrospective as blameless (focused on the system and process, not the individual) so the mentee stays engaged rather than defensive, and turn what's learned into a durable safeguard, not just a one-time talk.
Sequence: stabilize, then convene
- First, contain the actual consequence, ideally with the mentee involved rather than sidelined; solving it together protects both the outcome and their sense of ownership.
- Only after that, run the retrospective. Doing it while still firefighting mixes urgency with reflection and makes the mentee defensive.
The blameless postmortem as the concrete framework
- Ground rules stated up front: the goal is understanding the system and sequence of events, not assigning blame to the individual who happened to be the one who made the change.
- A neutral facilitator, or a rotating one across the team so it isn't always the same person in that role, helps keep the conversation from drifting toward blame, especially when the mentor is also the mentee's manager.
- Reconstruct a factual timeline first, before any discussion of what should have happened differently; jumping to "here's what you should have done" before the facts are laid out reads as judgment, not diagnosis.
- Sensitive details (who wrote the specific line, private context) get anonymized in the written artifact where possible, since the point is the process, not the person.
- The output is a written root-cause artifact with concrete action items, not just a conversation that ends when the meeting does.
Coaching the mentee specifically
- Ask them to walk through their own reasoning at each decision point, rather than you narrating what went wrong; this builds their own diagnostic skill for next time instead of just transmitting your conclusion.
- Separate the mistake from their competence explicitly, out loud; the message is "the system let this happen too easily," not "you're bad at this."
When the mistake isn't just one person's
- Sometimes the visible consequence comes from multiple people's individually reasonable changes interacting badly (a cross-team or cascading failure), not one person's error. The blameless frame matters even more here: the postmortem needs to surface the interaction, not scapegoat whichever team's change happened to be the trigger. The coaching conversation with your mentee shifts from "what would you do differently" to "how do you think about the blast radius of a change you don't fully control," since the lesson is about system boundaries, not individual judgment.
Worked example
A mentee I was supporting shipped a change that caused a visible, customer-facing issue. The first move was working alongside them to stabilize it, not taking over and pushing them out of the loop. Once it was stable, I ran a blameless postmortem with the mentee, a couple of the affected team members, and a neutral facilitator: we built a timeline from logs and commits before discussing anything about what should have happened, and the mentee walked through their own reasoning at each step rather than me presenting conclusions.
The root cause turned out to be a gap in the pre-merge checks, not a lapse in the mentee's judgment; the change was reasonable given what the tooling surfaced at the time. The written follow-up had concrete items (a new check added to the pipeline, an update to the review checklist) rather than just "be more careful." A few weeks later, in a separate incident, another engineer's change was caught by that new check before it shipped, which is the kind of signal that the fix generalized rather than just patching one person's blind spot.
Trade-offs and pitfalls
- The common junior mistake is either being too harsh in the moment (public correction, visible frustration), which teaches the mentee to hide mistakes next time, or being too soft and skipping the structured retrospective entirely, which loses the systemic fix.
- Blameless doesn't mean consequence-free; if the pattern repeats after a genuine fix and support, that's a different, harder conversation about capability or fit, not a postmortem.
- Anonymizing sensitive details in the artifact protects psychological safety (people's sense that they can admit a mistake without fear of punishment), but overdoing it (scrubbing so much nobody can learn the specific mechanism) makes the postmortem useless as a teaching tool. The balance is protecting the person while keeping the mechanism specific.
Design a highly available orchestration platform to handle 10,000 DAG runs per day and sustain 50,000 tasks per hour during peaks. Requirements: multi-region availability, per-team isolation, scheduling latency under 1s for ready tasks, support for backfills and ad-hoc runs, integration with Kubernetes workers, and a reasonable cost budget. Describe components, metadata storage, leader election, scaling strategies, and common failure modes.
Sample Answer
Direct answer
A high-availability orchestration platform handling 10,000 DAG runs a day and sustaining 50,000 tasks an hour at peak needs to treat the scheduler itself as the component under the most pressure, not the workers, since that peak rate works out to roughly 14 scheduling decisions a second sustained, and any single-scheduler design eventually hits metadata-database contention before it hits a raw compute ceiling. The architecture needs a horizontally scaled scheduler tier coordinated through leader election or ownership sharding, a metadata store partitioned for this write volume, and per-team isolation enforced at the actual resource-allocation layer, not only as a logical grouping.
Structured elaboration
graph TD
api[API / UI layer] --> meta[(Metadata store, partitioned)]
sched1[Scheduler replica 1] --> meta
sched2[Scheduler replica 2] --> meta
sched3[Scheduler replica N] --> meta
meta --> queue[Task queue]
queue --> k8s[Kubernetes worker pools, per region]
k8s --> meta
Metadata storage. A sharded or partitioned store is the platform's real bottleneck resource at this scale, partitioned by DAG or team, or by time range, so one team's burst does not contend for the same database rows or pages as everyone else's scheduling activity. Read replicas serve the UI and API layer's read-heavy queries, run history and dashboards, so those reads never compete with the scheduler's own write-heavy hot path.
Leader election. Multiple scheduler replicas run for availability, but assigning a specific task instance to a specific worker slot exactly once, avoiding two schedulers double-assigning the same task, needs either a single active leader coordinating assignment, elected through a distributed lock or a dedicated coordination service, or a carefully partitioned scheme where each replica owns a disjoint shard of DAGs. "Leader election" here really means "prevent two schedulers from racing on the same task," which true single-leader election and sharded ownership both solve, with different failure characteristics.
Multi-region availability. Workers run per region, close to where each region's own data and compute actually live, while the scheduling and metadata layer needs its own cross-region replication and failover strategy. A scheduler outage in one region should not stop task assignment for DAGs whose data does not require that region, which argues for spreading scheduler replicas across regions too, not only workers.
Per-team isolation. Enforced at the resource-allocation layer, dedicated worker pools and quotas per team, not only as a logical grouping in a dashboard, since logical-only isolation does nothing to stop one team's burst from starving another team's actual compute.
Sub-second scheduling latency for ready tasks. This requirement most directly rules out a scheduler that does a full metadata-database scan of every task across every DAG on each scheduling loop tick. At this scale the scheduler needs an efficient, indexed "what is ready right now" query, backed by the partitioning above, and a loop that runs frequently enough, or reacts to an event when a task's dependencies resolve rather than only polling, to hit sub-second latency consistently, not merely on average.
Backfills and ad-hoc runs. Given the isolation requirements above, backfill and ad-hoc capacity should be isolated from the live scheduling path's own capacity through separate worker pools, so a large backfill can never push live scheduling latency past its 1-second target.
Cost considerations. The scheduler and metadata tiers, the components the sub-second latency requirement forces to stay warm and over-provisioned for peak, are the platform's real fixed cost; keep that tier sized to the smoothed sustained rate plus real headroom for the thundering-herd case below, not statically sized to the instantaneous worst case, and prefer a small number of larger scheduler replicas over many small ones to reduce per-replica coordination overhead. Kubernetes worker pools are the opposite case: they should autoscale down to near zero outside peak hours rather than run warm around the clock, since worker compute, unlike the scheduler tier, has no availability requirement of its own between runs. Backfill and ad-hoc worker pools specifically are the best candidate for spot or preemptible instances, since that capacity is already isolated from the live scheduling path and, per the retry-friendly pattern described above, a preempted backfill task simply resumes rather than losing meaningful progress; the live, latency-sensitive worker pools serving the 1-second scheduling target should stay on stable, on-demand capacity, since a task reclaimed mid-run there directly threatens the latency requirement itself, the same reasoning that keeps a GPU training pool off spot capacity in a heterogeneous-workload design. Multi-region replication is a real, ongoing cost multiplier on both the metadata store and the scheduler tier; the requirement to justify it is genuine cross-region availability need, not applied by default to every component, since a region whose workers are already isolated per region does not automatically need its own full scheduler and metadata replica if a controlled failover to another region's scheduler tier meets the actual availability target.
Common failure modes at this scale. Metadata-database write contention becoming the actual throughput ceiling, more often than raw scheduler central-processing-unit ever does. A thundering herd at a popular fixed schedule time, many DAGs all triggered at, say, the top of every hour, producing a sharp burst rather than a smooth rate. Leader-election flapping under a network partition, a replica repeatedly losing and regaining leadership, causing duplicate or missed task assignments if the handoff logic is not itself carefully idempotent. Worker-pool autoscaling lag, new capacity taking real time to come online, causing a latency spike specifically at the start of a demand burst, before autoscaling has caught up.
Worked example
The stated peak, 50,000 tasks an hour, smooths out to:
360050000≈13.89 tasks/second sustained
But a thundering-herd scenario shows why the smoothed average understates real risk. If 30 percent of the 10,000 daily DAG runs are scheduled at one popular time, the top of an hour, that is 3,000 DAG runs concentrated into roughly the same minute. If each of those runs has an average of 8 tasks becoming ready simultaneously at trigger time, that is:
3000×8=24000 tasks
needing a scheduling decision within about that first minute, an instantaneous rate of:
6024000≈400 tasks/second
roughly 29 times the smoothed average rate, which is exactly the kind of burst that breaks a design sized only against the average.
Trade-offs and pitfalls
Sharding scheduler ownership by DAG avoids the coordination overhead of a single elected leader, but rebalancing when a new replica joins or an existing one dies becomes its own nontrivial problem, needing careful handling to avoid a window where some DAGs are owned by nobody, or by two replicas at once.
Over-partitioning the metadata store for write scalability can slow down certain read queries, a dashboard spanning many teams and DAGs at once now has to fan out across more partitions to answer, a real trade between write scale and read simplicity.
Treating sub-second scheduling latency as an average metric rather than a 99th- or 99.9th-percentile tail metric hides exactly the thundering-herd scenario above, which is precisely when a real user notices and complains, not during smooth, average-load periods.
Given a list of intervals, merge every pair that overlaps and return the resulting set of non-overlapping intervals. What is the key step that makes an O(n log n) solution possible, and what would you need to change if intervals could arrive one at a time instead of all at once?
Sample Answer
Direct answer
Sort the intervals by start time, then make a single linear pass, extending a running merged interval whenever the next interval's start is at or before its current end, and starting a new merged interval otherwise. The sort is what makes O(nlogn) possible: once intervals are ordered by start, every pair that can possibly overlap is adjacent in that order, so a single linear scan is enough to find every merge. If intervals arrive one at a time instead of all at once, you need a data structure that supports ordered insertion and neighbor lookup, such as a balanced binary search tree (BST, a tree that keeps keys ordered so lookup, insertion, and neighbor queries are all logarithmic) keyed by start time, rather than a one-shot sort.
Structured elaboration
Why sorting is the key step
Without an order, deciding whether interval A overlaps interval B requires comparing it against every other interval, an O(n2) scan overall. Sorting by start time establishes an invariant: once you have processed intervals in start order, the only interval that can still extend or overlap the one you are currently building is the very next one in the sorted order. That invariant is what collapses the overlap check from "compare against everything" to "compare against one neighbor," turning the merge itself into an O(n) linear pass after the O(nlogn) sort.
Batch algorithm (steps)
- Handle the empty-input case.
- Sort intervals by start time.
- Walk the sorted list, keeping a current interval: if the next interval's start is ≤ the current interval's end, extend the current end to the max of the two ends; otherwise, close out the current interval and start a new one from the next interval.
- Return the closed-out intervals.
Streaming variant
If intervals arrive one at a time and you must always be able to answer "what are the merged intervals so far," a one-shot sort no longer applies, since new intervals keep appearing. Two practical designs:
- Keep the current merged intervals in a balanced BST (or an ordered structure with the same guarantees) keyed by start time. On each new arrival, locate its insertion point in O(logn), check the neighbor(s) on both sides for overlap, and merge in place, splicing at most a bounded number of neighboring intervals per insertion.
- If you only need periodic snapshots rather than an always-current answer, buffer arrivals and re-run the batch algorithm on a schedule, trading immediacy for simplicity.
Worked example
def merge_intervals(intervals: list[list[int]]) -> list[list[int]]:
"""
Merge overlapping intervals. O(n log n) time (sort), O(n) space.
Assumes each interval is [start, end] with start <= end.
"""
if not intervals:
return []
ordered = sorted(intervals, key=lambda pair: pair[0])
merged = [ordered[0][:]]
for start, end in ordered[1:]:
last = merged[-1]
if start <= last[1]:
last[1] = max(last[1], end)
else:
merged.append([start, end])
return merged
if __name__ == "__main__":
sample = [[1, 3], [2, 6], [8, 10], [15, 18]]
print(merge_intervals(sample))
touching = [[1, 2], [2, 3]]
print(merge_intervals(touching))
Running this prints:
[[1, 6], [8, 10], [15, 18]]
[[1, 3]]
For [[1,3],[2,6],[8,10],[15,18]]: after sorting (already sorted here), [1,3] and [2,6] overlap since 2 <= 3, merging to [1,6]; [8,10] does not overlap [1,6] since 8 > 6, so it starts a new group; likewise [15,18]. For the touching pair [[1,2],[2,3]], 2 <= 2 counts as an overlap (touching intervals are treated as mergeable here), giving the single interval [1,3].
Complexity
Time: O(nlogn), dominated by the sort; the scan itself is O(n). Space: O(n) for the sorted copy and the output list (or O(1) extra if sorting and merging in place and the output does not count as extra space).
Edge cases
- Empty input returns an empty list.
- A single interval returns that interval unchanged.
- Touching intervals (end of one equals start of the next) are merged here; whether touching counts as overlapping is a modeling choice to state explicitly, since flipping the comparison from
<=to<changes the answer. - Intervals given with start greater than end (an inverted pair) should be rejected or normalized before sorting, since the algorithm assumes start <= end.
Trade-offs & pitfalls
The most common mistake is forgetting to sort at all, or sorting by end time instead of start time; the linear-scan step only works because sorting by start establishes the adjacency invariant above. A second common gap is not deciding, and stating, whether touching intervals count as overlapping: interviewers frequently probe exactly this boundary condition. For the streaming follow-up, the wrong turn is proposing to re-sort and re-scan the entire collection on every new arrival: that is correct but throws away the point of the question, which is to avoid O(n) work per insertion by using an ordered structure that supports local overlap checks near the insertion point.
Design a Spark Structured Streaming job to compute session-based metrics where late events can arrive up to 48 hours late. Explain watermark settings, state retention, checkpointing location, and how to size state store resources. Describe how you would handle late events beyond the watermark and how to backfill historical data without corrupting streaming state.
Sample Answer
Direct answer
Set the watermark to the full 48-hour late-arrival tolerance (withWatermark("event_time", "48 hours")), size the state store to hold every open session across that entire 48-hour window (not just the current moment), and route checkpointing to durable, versioned storage since a state store this large makes restart-from-scratch prohibitively expensive. Backfilling historical data safely means treating the backfill as a SEPARATE batch job writing into the same target table, never replaying old data through the LIVE streaming query's state, since replaying old events into an active watermark-bounded query either gets silently dropped (older than the current watermark) or corrupts the state store's notion of "current."
Structured elaboration
Watermark setting. withWatermark("event_time", "48 hours") tells Structured Streaming to keep a session/window's state open until the maximum observed event time advances 48 hours past that session's last event, meaning genuinely late events within that window are still correctly incorporated; anything later than 48 hours is dropped by design. This threshold is chosen entirely by the business requirement stated in the question (events can be up to 48 hours late), not by any Spark-internal default; a shorter watermark would silently drop legitimate late events the business has explicitly said to expect.
State retention and sizing state store resources. A 48-hour watermark means the state store must hold every open session (or window) whose data could still legitimately arrive, for up to 48 hours of wall-clock/event-time span, which for a high-volume session-metrics job can be a genuinely large amount of state (potentially many GB to TB, depending on session volume and per-session state size). This directly drives infrastructure sizing: executor memory/disk needs to accommodate the state store's expected size (Spark's default in-memory state store keeps state in executor memory backed by periodic snapshots to the checkpoint location; RocksDB-backed state store, spark.sql.streaming.stateStore.providerClass set to the RocksDB provider, moves the bulk of state to local disk with only a working set in memory, which matters specifically for state sizes that would not comfortably fit in-memory for a 48-hour retention window).
Checkpointing location. Given the state size implied by 48 hours of retention, checkpoint storage needs both the durability (a real, replicated store, not local-only) AND the throughput to handle periodic full or incremental state snapshots without becoming the pipeline's bottleneck; this is a case where the earlier general "reliable vs local checkpointing" trade-off resolves clearly toward reliable, high-throughput durable storage, since the state being protected is both large and expensive to rebuild from scratch.
Handling events beyond the watermark. Once an event's timestamp falls outside the 48-hour watermark window, Structured Streaming drops it from the stateful computation by design; there is no built-in mechanism to retroactively "un-drop" it into the live query. If genuinely-too-late events still need to be captured (for audit, or for a slower-but-more-complete reconciliation), the standard pattern is a SEPARATE sink capturing all raw events regardless of lateness (a raw landing table with no watermark logic applied), from which a periodic batch reconciliation job can correct the aggregated output after the fact, entirely outside the live streaming query's state.
Backfilling historical data without corrupting streaming state. Feeding old historical data through the SAME live streaming query is the specific failure mode to avoid: if the historical data's event times are older than the query's current watermark, it is silently dropped (no corruption, but also no effect, wasted work); if it happens to fall WITHIN the current watermark window, it can genuinely corrupt in-progress session/window state by mixing historical replay with live traffic in ways the downstream consumer of the output was not expecting. The safe pattern is a SEPARATE batch job, reading the same historical source, applying the identical session/window logic via the batch DataFrame API (the same code, since Structured Streaming and batch DataFrames share the same API and Catalyst optimizer), and writing to the target table with a clear boundary (a partition, a date range, or an explicit "backfill" marker) so the backfilled output is auditable and does not silently blend with or double-count the live query's output for the same period.
Worked example
A session-metrics pipeline: groupBy(session_window(event_time, "30 minutes"), user_id) with withWatermark("event_time", "48 hours"), writing finalized session summaries to a Delta table.
sessions = (events
.withWatermark("event_time", "48 hours")
.groupBy(F.session_window(F.col("event_time"), "30 minutes"), "user_id")
.agg(F.count("*").alias("event_count"), F.min("event_time").alias("session_start"),
F.max("event_time").alias("session_end")))
query = (sessions.writeStream
.outputMode("append")
.format("delta")
.option("checkpointLocation", "/checkpoints/session-metrics") # durable, replicated storage
.option("path", "/lake/session_metrics")
.trigger(processingTime="1 minute")
.start())
A discovered gap: three weeks of historical raw events were never processed by this pipeline (it was deployed after that data already existed). The correct backfill is a batch job:
historical = spark.read.format("delta").load("/lake/raw_events") \
.filter("event_time between '2026-07-01' and '2026-07-21'")
backfilled_sessions = (historical
.groupBy(F.session_window(F.col("event_time"), "30 minutes"), "user_id")
.agg(F.count("*").alias("event_count"), F.min("event_time").alias("session_start"),
F.max("event_time").alias("session_end"))
.withColumn("source", F.lit("backfill"))) # explicit marker distinguishing from live output
backfilled_sessions.write.format("delta").mode("append").save("/lake/session_metrics")
Running this as a batch job entirely separate from the live streaming query means the live query's checkpoint, watermark, and state store are never touched by the backfill, and the source="backfill" marker makes the two populations distinguishable for any downstream consumer that needs to know which rows came from which path.
Trade-offs and pitfalls
- The lookup-refresh problem: refreshing a slowly-changing reference/lookup table used INSIDE the streaming query (for example, a user-attributes table joined against the event stream) without triggering a large shuffle on every refresh is a related but distinct concern from state retention; the standard approach is a periodically-refreshed BROADCAST join against the lookup table (re-loaded on a schedule outside the streaming query's own micro-batch loop, using
foreachBatchto re-read and re-broadcast the lookup at controlled intervals) rather than re-joining against a large, un-broadcast lookup table on every micro-batch, which would add shuffle cost proportional to lookup table size on every single trigger. - Common mistake: setting the watermark shorter than the business's actual stated late-arrival tolerance to reduce state size, silently trading away data completeness the business explicitly asked for; if 48 hours of state genuinely does not fit the infrastructure budget, that is a capacity conversation to have explicitly, not a watermark value to quietly shrink.
- Common mistake: replaying historical data through the live query's Kafka (or other) source topic to "backfill" it, assuming the streaming job will just pick it up correctly; this is exactly the state-corruption/silent-drop failure mode described above, and the batch-job backfill pattern exists specifically to avoid it.
- 48 hours of state retention makes the RocksDB-backed state store provider worth strongly considering over the default in-memory provider, since in-memory state at this scale competes directly with executor heap needed for the rest of the computation, while RocksDB moves the bulk of state to local disk with a smaller in-memory working set, a trade-off (some added per-access latency for a much larger sustainable state size) that generally favors RocksDB once state size grows past what comfortably fits in a reasonable fraction of executor heap.
Design a plan-caching or statement-pooling strategy for a high-throughput OLTP system. What are the benefits, and what has to be true for cache invalidation to be safe when schema or statistics change underneath a cached plan?
Sample Answer
Direct answer. The benefit is avoiding the real, repeated cost of compiling a plan from scratch on every execution for a workload that runs the same query shapes very frequently; safe invalidation requires that any cached plan be tied to a version marker for both the schema and the statistics it was compiled against, so a change to either one forces recompilation rather than silently reusing a plan built for a world that no longer exists.
Structured elaboration. Compilation cost (parsing, planning, choosing among candidate strategies) is real and, for a query executed thousands of times a second, would dominate total cost if paid on every single execution; caching the compiled plan and reusing it across calls with different parameter values amortizes that cost to nearly zero per execution, which is the entire reason plan caching is the default behavior in most high-throughput OLTP (online transaction processing) systems rather than an optional optimization. The pitfall is invalidation: a cached plan was built against a specific schema (which indexes exist, which columns exist) and specific statistics (the data distribution at compile time); if the schema changes (an index dropped or added) or statistics change meaningfully after that plan was compiled, continuing to serve the old cached plan can silently produce an incorrect result (if the schema itself changed incompatibly) or, more commonly, a correct but badly suboptimal one (if only the data distribution shifted). Safe design tags every cached plan with the schema version and, where practical, a statistics-freshness marker it was compiled against, and evicts (forcing recompilation on next use) whenever either changes, rather than relying purely on a fixed time-based expiry that might invalidate too eagerly (wasting compilation cost) or too late (serving a stale plan for longer than safe).
Worked example. A high-throughput OLTP system serving the same handful of parameterized query shapes millions of times a day benefits enormously from plan caching, the compilation cost paid once per shape, amortized across millions of executions, is a rounding error; the same system dropping an index that a cached plan depended on, without invalidating that specific cached plan, risks either an error or a silent fallback to a much worse strategy the next time that plan gets reused, until something eventually forces a recompile.
Trade-offs and pitfalls. This same caching mechanism is exactly what creates the parameter-sniffing risk discussed elsewhere in this topic: a plan compiled once and reused across very different parameter values can become mismatched to the CURRENT execution's actual selectivity even when the schema and statistics haven't changed at all; a robust plan-caching design has to account for both invalidation risk (schema/statistics changing) and this separate parameter-appropriateness risk (the same schema and statistics, but a skewed value distribution) as two distinct failure modes, not one.
Build a capacity-planning model for the storage and compute costs of an analytics platform that grows predictably with usage, accounting for retention, partitioning, and compute sizing for both ETL/ELT and interactive queries. Forecast costs 12-24 months out and describe how you would validate the model.
Sample Answer
A capacity-planning model has to connect three growing inputs (data volume, retention, and query concurrency) to two cost drivers (storage and compute) with enough transparency that someone can challenge your assumptions later.
The model
Storage cost scales with retained data volume, which is a function of daily ingestion volume and retention period:
StorageTB=DailyIngestGB×365×RetentionYears/1000Compute cost has two components: scheduled ETL/ELT (extract, transform, load / extract, load, transform) jobs, roughly proportional to data volume processed, and interactive query compute (roughly proportional to concurrent users and query complexity, largely independent of total data volume if partitioning is effective):
ComputeCost=(DailyIngestGB×ETLCostPerGB)+(ConcurrentUsers×AvgQueriesPerUserPerDay×CostPerQuery)Worked example with pinned inputs
Assume: daily ingestion of 500 GB per day, a 2-year retention policy, 50 concurrent analysts averaging 20 queries per day each, and illustrative, platform-specific unit rates of 0.02 cost-units per GB-month for storage, 0.01 cost-units per GB processed for ETL compute, and 0.05 cost-units per query for interactive compute (substitute your own platform's actual billed rates here).
Storage: 500 GB/day times 365 days times 2 years equals 365,000 GB, or 365 TB, retained after two years. At 0.02 cost-units per GB-month, that is roughly 7,300 cost-units per month once fully ramped (this grows steadily over the two years as retained volume accumulates; it is not the month-1 cost).
ETL compute: 500 GB/day times 0.01 cost-units per GB times 30 days equals 150 cost-units per month.
Interactive compute: 50 users times 20 queries/day times 30 days times 0.05 cost-units per query equals 1,500 cost-units per month.
Total steady-state monthly cost at the 2-year retention horizon: roughly 7,300 plus 150 plus 1,500, or about 8,950 cost-units per month, with storage dominating because it compounds over the retention window while compute scales with current usage, not accumulated history.
Forecasting 12-24 months out
Apply a growth rate to daily ingestion and concurrent users (say, a business-projected 20 percent year-over-year data growth and 15 percent analyst-headcount growth) and recompute the same formulas at each future point; the storage term compounds fastest because it's a function of accumulated volume over the growing retention window, not just the current day's ingestion, which is precisely why storage tends to dominate total cost at scale even though its per-unit price is far cheaper than compute.
Validating the model
Compare the model's projected cost for the CURRENT month (using today's actual ingestion volume and concurrency) against the actual current bill; if they diverge by more than a small margin, the unit-cost assumptions are wrong and need recalibrating against real invoices before trusting the 12-24 month projection. A model that isn't first validated against a month you can already observe is not a forecast, it's a guess with a formula attached.
Trade-offs and pitfalls
The most common mistake is projecting compute cost as though it scales with total data volume the way storage does; well-partitioned interactive queries scan a bounded slice of data regardless of how much history is retained, so compute growth is really driven by user count and query complexity, not by retention. Ignoring that distinction produces a model that wildly overestimates future compute cost and underinvests in the partitioning discipline that would keep it flat.
Rather than assuming blameless postmortems and structured learning practices reduce incident recurrence, design an experiment or quasi-experiment that would actually demonstrate it. Define your primary metrics, how you would form treatment and comparison groups given that incidents are relatively low-frequency, and what confounders you would need to control for.
Sample Answer
Direct answer
Proving blameless postmortems causally reduce recurrence, rather than assuming it, requires comparing incident outcomes between groups that did and did not receive the full blameless-postmortem treatment, while controlling for the fact that incidents are relatively rare, which makes a small, underpowered comparison unreliable.
Structured elaboration
- Define the primary metric precisely. Incident recurrence rate for the same or closely related failure category within a defined window (say, six months) after a postmortem, and mean-time-to-recovery for any recurrence that does happen, are both reasonable primary outcomes.
- Form comparison groups given low incident frequency. A staggered rollout across teams (some teams adopt full blameless postmortems now, others adopt a few months later) gives you a natural comparison without denying anyone the practice indefinitely, and it's more feasible than a strict randomized controlled trial in most organizations. Alternatively, compare incident classes that received a full postmortem against similar-severity incident classes from before the practice was adopted, using the organization's own history as the comparison.
- Account for low frequency directly. Because a single team's incident count is small, aggregate across many teams or many incident categories to get enough statistical power, and be honest that with genuinely rare, high-severity incidents, you may only be able to speak confidently about a proxy (like recurrence of the underlying vulnerability class in code review or testing) rather than recurrence of an actual outage.
- Control for confounders explicitly. Teams that adopt blameless postmortems early are often also the teams already investing more broadly in reliability practices, so any observed improvement could be due to that general investment rather than the postmortem practice specifically; a staggered rollout across otherwise-similar teams helps isolate this, and tracking a secondary metric less directly tied to postmortems (like general code quality trends) as a check helps rule out a confound affecting everything at once.
- Report the honest limitation. Even a well-designed study in this space will likely have wide confidence intervals given how rare severe incidents genuinely are; report that uncertainty rather than overstating confidence in a clean causal result.
Worked example
An organization with 40 teams rolls out mandatory blameless postmortems to half the teams (chosen to be broadly similar in size and incident history) starting this quarter, with the other half adopting the practice three months later. Primary metric: recurrence rate of a related incident category within six months of any postmortem-eligible incident. After the study window, teams in the early-adoption group show a lower recurrence rate than the later-adoption group during the period before the second group adopted the practice, and the gap narrows once the second group also adopts it, which is more convincing evidence of a causal effect than a simple before-and-after comparison on a single group would have been, since it rules out a general org-wide trend as the sole explanation.
Trade-offs and pitfalls
The most common mistake is treating a simple before-and-after comparison on one group as proof of causation, when it's equally consistent with unrelated organizational improvements happening over the same period. A second is understating how much statistical power genuinely rare, severe incidents cost you, and presenting a result with far more confidence than the small sample size actually supports.
Recommended Additional Resources
- LeetCode SQL Problems and Medium difficulty+ Data Structures/Algorithms problems (1-2 months prep)
- Leetcode Study Plan for Data Engineer (medium to hard tier)
- Designing Data-Intensive Applications by Martin Kleppmann (systems design foundation)
- Cracking the PM Interview by McDowell & Bavaro (product thinking for technical roles)
- Meta Engineering Blog and System Design Case Studies (learn from Meta's real challenges)
- InterviewQuery.com - Meta specific data engineering interview guides and mock interviews
- Glassdoor and TeamBlind - Real Meta interview experiences and questions from recent candidates
- Mode Analytics SQL Tutorial and Stratascratch (platform for practicing actual company SQL questions)
- Udacity Data Engineering Nanodegree or DataCamp Data Engineering courses (pipeline architecture foundation)
- Official Apache Airflow, Spark, and Kafka documentation (hands-on with key technologies)
- Designing Machine Learning Systems by Chip Huyen (metrics and experimentation chapter relevant for product sense)
- YouTube channels: Seattle Data Guy, Andreas Kretz (real-world data engineering scenarios)
Search Results
Meta Data Engineer Interview (questions, process, prep) - IGotAnOffer
Tell me about yourself. Tell me about a challenge you faced and how you overcame it. Why data engineering? Why Meta? Tell me about a project you ...
Meta Data Engineer - the 2025 Interview Guide - Prepfully
Interview Questions · Tell me about yourself. · Tell me about your most recent Data Engineering project? How did you decide what to do? Who was involved? · What do ...
Meta Data Engineer 2025 Interview Experience | Tech Industry - Blind
1) For product sense - How many metrics are we expected to state? Considering 10 min allocation for this how depth will it usually go?
Meta Data Engineer Interview Questions: Process, Preparation, and ...
Discover everything you need to succeed in your Meta Data Engineer interview: a detailed process overview, sample interview questions, ...
Meta Data Engineer Interview in 2025 (Leaked Questions)
3.4 Behavioral Questions · Why do you want to work as a Data Engineer at Meta? · Describe a time when you had to work with cross-functional ...
Meta Data Engineer Interview Guide | Sample Questions (2025)
Sample Interview Questions · Why Meta? · Tell me about a time you led a project. · How do you ensure accurate stakeholder requirements? · Tell me about a ...
This interview preparation guide was generated using AI-powered research from the sources listed above. While we strive for accuracy, we recommend verifying critical information from official company sources.
Want to create your own tailored preparation guide using our deep research?
Get Started for FreeInterview-Ready Courses
Visual-first, interactive, structured learning paths