← Meta Interview Insights

Meta·Software Engineer·Technical Phone Screen·Senior

Senior
May 2026

Summary

Meta data engineer interview that was basically a gauntlet of SQL and Python thrown at you in one sitting. Heavy on the engineering side, almost no soft skills stuff, which I wasn't fully expecting.

Questions Asked (7)

Q1

Given a clickstream events table and a users table, write SQL to compute DAU, WAU, and MAU.

Product Analytics & MetricsData Modeling
Author's notes

Seemed straightforward at first and I kind of rushed it.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the definitions of DAU, WAU, and MAU in terms of the clickstream events table, then write separate queries that count distinct users per day, week, and month. Use date functions to truncate event timestamps to the appropriate granularity and join with the users table if needed to filter valid users.

Pro tip: Mention that DAU/WAU/MAU are typically computed on a rolling basis (e.g., last 7 days) rather than calendar weeks, and clarify the time zone and event type (e.g., only 'click' events) to avoid ambiguity.

1. Clarify definitions and assumptions

Confirm what constitutes an active user (e.g., any event vs. specific event type) and the time windows (calendar vs. rolling). Also check if the users table is needed to filter out bots or inactive accounts.

2. Identify relevant columns and date functions

Locate the user_id and event_timestamp columns in the clickstream table. Determine the SQL date functions to truncate timestamps to day, week, and month (e.g., DATE_TRUNC, DATE_FORMAT).

3. Write DAU query

Count distinct user_id per day by grouping on the truncated date. Optionally join with users table to include only valid users.

4. Write WAU and MAU queries

Similarly, count distinct user_id per week and per month using appropriate date truncation. For rolling metrics, use a window function or self-join to count distinct users in the last 7 or 30 days.

5. Combine results and discuss optimization

If needed, combine the three metrics into a single query using conditional aggregation or UNION ALL. Mention indexing on user_id and event_timestamp for performance.

Key Points to Mention

  • Definition of an active user (e.g., any event vs. specific event types)
  • Time granularity: calendar day/week/month vs. rolling 7/30 days
  • Use of COUNT(DISTINCT user_id) to avoid double-counting
  • Date truncation functions (e.g., DATE_TRUNC('week', event_timestamp))
  • Handling time zones and data freshness
  • Performance considerations: indexing, partitioning, and avoiding full table scans

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Using the same schema, write SQL for D1 and W1 retention cohorts.

Product Analytics & MetricsData Modeling
Author's notes

This one took me a minute to set up correctly.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

First, clarify the schema and definitions of D1 and W1 retention (e.g., D1 = users who return the day after signup, W1 = users who return within 7 days). Then, write a SQL query that identifies cohorts by signup date, calculates retention based on activity dates, and aggregates results. Use a consistent date logic and handle edge cases like time zones.

Pro tip: Mention that you would validate the retention definition with stakeholders and consider using a calendar date table to handle gaps in activity data, ensuring accurate cohort sizes.

1. Clarify definitions and schema

Confirm what D1 and W1 retention mean (e.g., D1: user returns exactly 1 day after signup; W1: user returns within 7 days). Identify key tables: users (with signup date) and events (with user_id and activity date).

2. Identify cohorts

Group users by their signup date to form daily cohorts. For each cohort, calculate the total number of users.

3. Calculate retention

For each cohort, determine which users performed the desired action (e.g., logged in) on the target day(s). Use date arithmetic (e.g., DATE_ADD) to compare activity date to signup date.

4. Aggregate and compute rates

Join cohort sizes with retained user counts, compute retention rate as retained users divided by cohort size, and format the output (e.g., by cohort date).

5. Optimize and validate

Consider indexing, use CTEs for readability, and validate results with sample data or known benchmarks.

Key Points to Mention

  • Definition of D1 and W1 retention (exact vs. within period)
  • Use of date functions (e.g., DATE_ADD, DATEDIFF) to calculate day differences
  • Handling of time zones and date boundaries
  • Use of LEFT JOIN to include users with no activity
  • Aggregation by cohort date and calculation of retention rate
  • Performance considerations (indexes, partitioning)

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q3

How would you sessionize clickstream events using SQL, and what metrics would you compute per session?

Data ModelingProduct Analytics & Metrics
Author's notes

My favorite part of the whole thing.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by explaining the concept of sessionization: grouping user events into sessions based on a timeout (e.g., 30 minutes of inactivity). Then describe a SQL approach using window functions to identify session boundaries and assign session IDs, and finally list key metrics like session duration, page views, and conversion rate.

Pro tip: Mention that sessionization can be done efficiently with a single pass using window functions, and consider edge cases like multiple sessions per user per day and handling of late-arriving data.

1. Define session boundaries

Explain that a session starts with the first event and ends after a period of inactivity (e.g., 30 minutes). Use the LAG function to compare timestamps and flag new sessions when the gap exceeds the threshold.

2. Assign session IDs

Use a cumulative sum of the new session flags to assign a unique session ID per user. This can be done with SUM() OVER (PARTITION BY user_id ORDER BY event_time).

3. Compute session-level metrics

Aggregate events by session ID to calculate metrics such as session start/end time, duration, number of events, and distinct pages visited.

4. Derive business metrics

From session-level data, compute higher-level metrics like bounce rate, conversion rate, and average session duration per user or cohort.

5. Optimize and handle edge cases

Discuss performance considerations (e.g., partitioning, indexing) and edge cases like sessions spanning midnight or multiple sessions in a short period.

Key Points to Mention

  • Use of window functions (LAG, SUM OVER) for sessionization
  • Session timeout threshold (e.g., 30 minutes) and its impact
  • Metrics: session duration, page views per session, bounce rate, conversion rate
  • Handling of multiple sessions per user and per day
  • Performance optimization: partitioning by user_id, ordering by event_time
  • Edge cases: late-arriving events, sessions crossing midnight

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q4

Design an incremental daily job that updates aggregation tables idempotently. How do you use MERGE or INSERT patterns alongside window functions to make this work?

System DesignData ModelingTechnical Trade-offs
Author's notes

Blanked for a second on the idempotency framing.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: what aggregation tables, what grain, what source data, and how late-arriving data is handled. Then describe a two-phase approach: first compute the incremental delta using window functions to identify new or changed records, then apply the delta to the aggregation table using an idempotent MERGE or INSERT ... ON CONFLICT pattern. Emphasize how the design ensures exactly-once semantics and handles reruns safely.

Pro tip: Mention that idempotency is best achieved by making the job deterministic and keyed on a natural business key plus a processing date, so rerunning the same partition produces the same result. Also note that using MERGE with a source that includes only the latest version per key (via ROW_NUMBER) avoids duplicate updates and is more efficient than deleting and reinserting.

1. Clarify requirements and constraints

Ask about the aggregation grain, source tables, update frequency, data volume, and how late or out-of-order data is handled. Confirm whether the job must be exactly-once and what the SLA is.

2. Design the incremental extraction with window functions

Use window functions like ROW_NUMBER() or RANK() to deduplicate source data and select the latest record per key, and use LAG/LEAD or date filters to identify only new or changed rows since the last run. This minimizes the delta to process.

3. Apply idempotent writes with MERGE or INSERT ON CONFLICT

Use MERGE (or INSERT ... ON CONFLICT DO UPDATE) to upsert the delta into the aggregation table, matching on the aggregation key. Ensure the merge condition includes a timestamp or version to avoid overwriting newer data with older data.

4. Handle late-arriving data and reprocessing

Explain how to handle late data by either reprocessing affected partitions or using a merge that updates aggregates for the impacted keys. Show how the same logic can be rerun for a given date range without duplicating results.

5. Discuss trade-offs and operational concerns

Compare MERGE vs. INSERT patterns in terms of performance, locking, and complexity. Mention partitioning, indexing, and monitoring to ensure the job scales and is observable.

Key Points to Mention

  • Idempotency: rerunning the job for the same partition yields the same result, often achieved by keying on a natural key and processing date.
  • Window functions: ROW_NUMBER() to deduplicate, LAG/LEAD to detect changes, and SUM/COUNT OVER for incremental aggregation.
  • MERGE statement: syntax and semantics for upserting, including matching on the aggregation key and handling updates vs. inserts.
  • INSERT ... ON CONFLICT (PostgreSQL) or INSERT OVERWRITE (Hive/Spark) as alternatives, with trade-offs in performance and atomicity.
  • Late-arriving data: strategies like reprocessing partitions, using a merge that updates affected aggregates, or maintaining a staging table.
  • Partitioning and indexing: how to partition the aggregation table (e.g., by date) and index the merge key to keep the job efficient.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q5

How do you detect and handle duplicate events and late-arriving data in a pipeline?

Root Cause AnalysisTechnical Trade-offsSystem Design
Author's notes

Said something about using ROW_NUMBER partitioned by a natural key to deduplicate, and watermarks for late events.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the pipeline's requirements and constraints, then explain how you detect duplicates and late data using techniques like event-time processing, watermarks, and idempotent operations. Finally, discuss trade-offs between correctness, latency, and cost, and how you handle late data with strategies like allowed lateness, side outputs, or reprocessing.

Pro tip: Emphasize that you design for idempotency and exactly-once semantics from the start, and mention how you monitor and alert on duplicate and late data rates to catch issues early.

1. Clarify requirements and constraints

Ask about data sources, volume, latency requirements, and business impact of duplicates or late data. This shows you understand the problem context before diving into solutions.

2. Detect duplicates and late data

Explain methods like unique event IDs, deduplication windows, and event-time vs processing-time comparison. Mention monitoring metrics like duplicate rate and lateness distribution.

3. Handle duplicates

Describe idempotent writes, deduplication keys, and exactly-once processing frameworks (e.g., Flink, Kafka). Discuss trade-offs between at-least-once and exactly-once.

4. Handle late-arriving data

Cover strategies like watermarks with allowed lateness, side outputs for late events, and reprocessing or backfilling. Explain how you decide when to drop vs. process late data.

5. Discuss trade-offs and monitoring

Summarize trade-offs between correctness, latency, and cost. Highlight the importance of monitoring, alerting, and iterative improvement.

Key Points to Mention

  • Event-time vs processing-time processing
  • Watermarks and allowed lateness
  • Idempotent operations and exactly-once semantics
  • Deduplication techniques (e.g., unique IDs, bloom filters)
  • Side outputs or dead-letter queues for late data
  • Monitoring and alerting on duplicate and late data rates

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q6

Write a Python script (no heavy frameworks) that parses semi-structured JSON from the properties column, normalizes nested fields, and writes the output as partitioned Parquet files.

Technical Trade-offsData Modeling
Author's notes

Used json.loads in a loop with some try/except for malformed records, then pandas for the normalization and pyarrow to write Parquet.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the schema and partitioning strategy, then outline a lightweight pipeline using pandas and pyarrow to parse JSON, flatten nested fields, and write partitioned Parquet. Emphasize trade-offs around memory, schema evolution, and partition granularity.

Pro tip: Mention that you'd first sample the JSON to infer a schema and handle edge cases like missing keys or type inconsistencies, and use pyarrow's dataset API for efficient partitioned writes without loading everything into memory.

1. Clarify requirements and constraints

Ask about the expected JSON structure, partitioning keys (e.g., date, region), and volume of data to determine if a streaming or batch approach is needed.

2. Design the parsing and normalization logic

Use pandas.json_normalize to flatten nested JSON, handle missing fields, and enforce a consistent schema across records.

3. Implement partitioned writing

Leverage pyarrow to write Parquet files partitioned by the chosen keys, using a dataset writer to avoid loading all data into memory.

4. Validate and optimize

Check output for schema consistency, partition pruning efficiency, and file sizes; consider compression and row group sizing for performance.

Key Points to Mention

  • Use of pandas.json_normalize for flattening nested JSON structures
  • PyArrow's ParquetWriter and dataset API for partitioned writes
  • Handling schema evolution and missing fields with default values or nullable types
  • Trade-offs between partition granularity and number of files (small files problem)
  • Memory management: chunking or streaming large JSON inputs
  • Validation of output schema and data quality checks

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q7

How would you write basic unit tests for the data-cleaning script you just described?

Technical Trade-offs
Author's notes

Quick question at the end.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by outlining a testing strategy that covers both happy paths and edge cases for each data-cleaning function. Emphasize the use of a testing framework like pytest or unittest, and describe how you would structure tests to be fast, isolated, and maintainable. Conclude by mentioning how you would integrate these tests into a CI pipeline to catch regressions early.

Pro tip: Use parameterized tests to efficiently cover multiple input-output scenarios, and always include tests for malformed or unexpected data to ensure robustness. This demonstrates foresight and a quality-first mindset that Meta values.

1. Identify testable units

Break down the data-cleaning script into individual functions or methods, such as handling missing values, type conversions, or deduplication. Each unit should be tested in isolation to pinpoint failures.

2. Define expected behavior and edge cases

For each unit, specify the expected output for typical inputs and enumerate edge cases like empty datasets, null values, or unexpected formats. This ensures comprehensive coverage.

3. Choose a testing framework and write tests

Select a framework like pytest or unittest, and write test functions that assert the expected outcomes. Use fixtures or setup methods to create consistent test data.

4. Run tests and measure coverage

Execute the tests locally and use coverage tools to identify untested code paths. Aim for high coverage but prioritize critical paths.

5. Integrate into CI/CD

Configure the tests to run automatically on each commit or pull request using a CI service like GitHub Actions or Jenkins. This ensures early detection of regressions.

Key Points to Mention

  • Use of a standard testing framework (e.g., pytest, unittest) and assertion methods.
  • Testing both normal and edge cases, including malformed data and empty inputs.
  • Isolation of tests: each test should be independent and not rely on external state.
  • Mocking or stubbing external dependencies (e.g., file I/O, database connections) to keep tests fast and deterministic.
  • Parameterized tests to reduce boilerplate and cover multiple scenarios.
  • Integration with CI/CD pipelines for automated testing.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.