Amazon Data Engineer Interview Preparation Guide (Mid-Level)
Amazon's Data Engineer interview process consists of 3 main phases: an initial recruiter screening call, a technical phone screen focused on SQL and data modeling, and an onsite interview loop (3-4 interviews) that includes two technical interviews assessing problem-solving through scenario-based questions, a Bar Raiser round evaluating cultural fit and critical thinking, and a behavioral round focused on Amazon's Leadership Principles. For mid-level candidates, the process emphasizes hands-on technical proficiency, ability to own medium-sized projects independently, and demonstrated mentorship potential.
Interview Rounds
Recruiter Screening
What to Expect
Your initial contact with Amazon's recruiting team via phone call. The recruiter will verify your background, confirm your interest in the Data Engineer role, explain the interview process, and assess cultural alignment and basic qualifications. This is an opportunity for you to ask clarifying questions about the role, team, and expectations. Recruiters are looking for communication skills, enthusiasm, and confirmation that you understand the role's requirements.
Tips & Advice
Prepare a concise 2-minute summary of your background emphasizing relevant data engineering projects and technologies. Research the specific team or business area you're interviewing for if available. Be enthusiastic about Amazon's mission and the Data Engineer role. Ask thoughtful questions about team structure, current challenges, and what success looks like in the role. Confirm timing and logistics for the technical phone screen. Write down key information the recruiter shares about the role and team.
Focus Topics
Motivation and Fit for Amazon
Prepare thoughtful reasons for why you want to work at Amazon as a Data Engineer, specific to the company (not generic reasons). Research Amazon's technology stack, recent initiatives in data engineering, and how the company uses data to drive decisions. Consider how Amazon's leadership principles align with your values.
Practice Interview
Study Questions
Understanding the Data Engineer Role at Amazon
Familiarize yourself with the specific responsibilities of a Data Engineer at Amazon: building and maintaining data collection, storage, and processing infrastructure; designing and implementing data pipelines; creating data warehouses and lakes; developing ETL processes; ensuring data quality and consistency; and working with big data technologies like Spark, Hadoop, and AWS services. Understand how this role connects to Amazon's business and data science teams.
Practice Interview
Study Questions
Professional Background Summary
Develop a 2-minute elevator pitch covering your experience, key projects (especially data engineering work), and relevant technical skills. Highlight specific achievements with quantifiable impact. For a mid-level candidate, emphasize project ownership, technical growth, and collaboration with cross-functional teams.
Practice Interview
Study Questions
Technical Phone Screen
What to Expect
A 45-60 minute technical interview conducted via phone or video with an Amazon Data Engineer. This round focuses on assessing your SQL proficiency and data modeling skills—critical competencies for the role. You will be asked to write and optimize SQL queries, design database schemas, and discuss real-world data modeling scenarios. The interviewer may use a shared code editor or whiteboarding tool. You'll need to think aloud, explain your approach, and justify your design decisions. This round evaluates both correctness and your ability to communicate technical thinking.
Tips & Advice
Practice SQL on platforms like LeetCode or DataLeetCode focusing on joins (INNER, LEFT, FULL OUTER), aggregations, window functions, CTEs, and subqueries. Be prepared to optimize queries for performance and explain your optimization strategy. For data modeling, practice designing schemas for real-world scenarios (e.g., e-commerce transactions, user activity). Communicate your thought process clearly—explain what problem you're solving and why you chose your approach. Ask clarifying questions if the problem statement is ambiguous. Test your SQL syntax mentally or request to write it out step-by-step before finalizing. Manage your time: if you're stuck on a problem, communicate your stuck point and move forward rather than silent struggling.
Focus Topics
Problem Analysis and Communication
When given a problem, clarify requirements and constraints before jumping to implementation. Ask questions: What data do we have? What are the access patterns? Are there performance constraints? Once you understand the problem, communicate your approach before coding. As you code, think aloud and explain your reasoning. A mid-level candidate should demonstrate structured problem-solving: break complex problems into smaller components, discuss trade-offs, and justify decisions.
Practice Interview
Study Questions
SQL Fundamentals and Optimization
Master SQL fundamentals including SELECT, WHERE, JOIN (INNER, LEFT, RIGHT, FULL OUTER), GROUP BY, HAVING, ORDER BY. Progress to intermediate concepts: window functions (ROW_NUMBER, RANK, LAG, LEAD), CTEs (Common Table Expressions), subqueries (correlated and non-correlated), UNION/UNION ALL, and set operations. Practice writing efficient queries and understand query optimization techniques such as indexing strategy, avoiding N+1 queries, and query execution plans. For a mid-level candidate, you should be able to write complex queries and explain optimization trade-offs.
Practice Interview
Study Questions
Data Modeling and Schema Design
Understand relational database design principles: normalization (1NF, 2NF, 3NF), denormalization trade-offs, and when to apply each. Practice designing schemas for various domains (e-commerce, social media, analytics). Understand different schema patterns: star schema, snowflake schema (for dimensional modeling), and OLTP vs OLAP design considerations. For a mid-level candidate, be able to make design decisions based on access patterns, scalability needs, and business requirements. Understand the trade-offs between normalization and query performance.
Practice Interview
Study Questions
Onsite Technical Interview 1: Data Pipeline and ETL Design
What to Expect
This is the first of multiple onsite rounds (typically 45-60 minutes) where you'll meet an Amazon Data Engineer at the office or via video. This round focuses on your ability to design and implement data pipelines and ETL processes. You'll be presented with real-world scenarios (e.g., ingesting and processing large volumes of transaction data, building a data pipeline to support analytics) and asked to design solutions. The interviewer will dig deep into your approach: How would you extract data from various sources? How would you transform and validate it? How would you handle failures and ensure data quality? You may be asked to write code, draw architecture diagrams, or discuss your design verbally. The round emphasizes problem-solving, system thinking, and understanding of distributed data processing.
Tips & Advice
Approach this round as a design discussion, not just a coding exercise. Start by clarifying the problem: data sources, volume, latency requirements, data quality needs. Propose an end-to-end solution that includes data ingestion, transformation, storage, and error handling. For a mid-level candidate, you should discuss real technologies like Spark, Kafka, AWS Glue, or Lambda, but focus on conceptual understanding and design trade-offs rather than implementation details. Discuss failure modes: What if the data source is unavailable? What if there are malformed records? How would you detect and handle data quality issues? Be prepared to justify your technology choices based on requirements. Draw diagrams to illustrate your pipeline architecture. Ask follow-up questions about requirements that might change your design.
Focus Topics
Data Quality, Validation, and Error Handling
Design data quality checks into your pipelines: validate data completeness, accuracy, timeliness, and consistency. Implement checks for schema validation, duplicate detection, outlier detection, and business logic validation. Design error handling strategies: what happens when validation fails? Should the pipeline retry, alert, quarantine bad data, or fail fast? For mid-level engineers, demonstrate understanding of data quality frameworks and best practices for ensuring reliable data in production systems.
Practice Interview
Study Questions
Distributed Computing Frameworks: Spark, Hadoop, and AWS Tools
Develop working knowledge of distributed computing frameworks commonly used at Amazon: Apache Spark (RDD, DataFrame API, SQL), Hadoop (HDFS, MapReduce), and AWS-native tools (AWS Glue, EMR, Lambda). Understand when to use each tool. Know Spark fundamentals: resilient distributed datasets, transformations vs actions, partitioning, caching. For mid-level engineers, be comfortable discussing Spark job optimization, understanding execution plans, and choosing between different APIs for a given problem.
Practice Interview
Study Questions
Scalability, Performance Optimization, and Cost Considerations
Design pipelines that scale horizontally to handle growing data volumes. Understand performance optimization: partitioning strategies, compression, indexing, query optimization. Consider cost optimization: choosing appropriate compute resources (on-demand vs reserved), using spot instances, optimizing storage (tiering, archival). For mid-level candidates, discuss trade-offs between performance, cost, and complexity. Understand how decisions impact overall system efficiency.
Practice Interview
Study Questions
ETL Process Design and Implementation
Understand the Extract-Transform-Load process end-to-end. Design ETL workflows that ingest data from various sources (APIs, databases, files, streaming systems), apply transformations (cleaning, aggregation, enrichment, deduplication), and load data into target systems (data warehouses, data lakes, operational databases). For mid-level engineers, be able to design ETL processes that handle scale, implement incremental loading strategies, manage state and checkpoints, and ensure idempotency (same input always produces same output regardless of retries).
Practice Interview
Study Questions
Data Pipeline Architecture and Real-Time vs Batch Processing
Design scalable, fault-tolerant data pipelines that support both batch and real-time processing. Understand batch processing (Spark, Hadoop MapReduce) for large-scale data transformations and real-time processing (Kafka, Spark Streaming, Lambda) for continuous data flows. Discuss trade-offs: batch is generally lower cost and simpler for complex transformations; real-time provides lower latency but is more complex. For mid-level candidates, be able to design pipelines that choose appropriate processing models based on requirements. Understand concepts like windowing, late-arriving data, and exactly-once semantics.
Practice Interview
Study Questions
Onsite Technical Interview 2: Data Modeling, SQL, and Database Optimization
What to Expect
This second technical onsite round (typically 45-60 minutes) with another Amazon Data Engineer focuses on deeper data modeling and SQL skills in the context of data warehousing and analytics. You'll be given complex scenarios requiring you to design schemas for analytics workloads, write sophisticated SQL queries for real business problems, and optimize database performance. The interviewer may present a business problem and ask you to design a data model that supports it, then write queries to extract insights. You'll be evaluated on your ability to design efficient schemas, write correct and performant SQL, understand indexing and query optimization, and explain trade-offs in your design decisions.
Tips & Advice
Before writing SQL, design the schema carefully. Ask clarifying questions: What are the key queries we need to support? How much data will we have? What are the access patterns? Design schemas that support efficient query patterns—this is more important than normalized perfection. When writing SQL, start simple and optimize if needed. Use window functions, CTEs, and subqueries effectively. Explain your indexing strategy and discuss query optimization. For mid-level candidates, demonstrate understanding of dimensional modeling, fact and dimension tables, slowly changing dimensions, and analytics-specific schema patterns. Discuss trade-offs between different schema designs based on requirements.
Focus Topics
OLAP vs OLTP Database Design
Understand the distinction between Online Analytical Processing (OLAP) and Online Transaction Processing (OLTP) systems. OLTP systems are optimized for fast, frequent transactions with normalized schemas and row-oriented storage. OLAP systems are optimized for complex analytical queries over large datasets with denormalized schemas and column-oriented storage. For mid-level engineers, understand when to use each approach and how database design differs. Discuss how data flows from OLTP to OLAP systems in a data warehouse architecture.
Practice Interview
Study Questions
Query Optimization and Indexing Strategy
Understand query execution plans and how to interpret them to identify bottlenecks. Discuss indexing strategies: B-tree indexes for range queries, hash indexes for equality, composite indexes for multi-column predicates. Understand query optimization techniques: join order optimization, predicate pushdown, column pruning, cardinality estimation. For mid-level candidates, be able to analyze a slow query, identify the root cause, and suggest optimizations (indexes, query rewrites, table redesign).
Practice Interview
Study Questions
Dimensional Modeling and Star/Snowflake Schemas
Master dimensional modeling concepts used in data warehousing: fact tables (measurable events), dimension tables (contextual information), slowly changing dimensions (SCD types 1, 2, 3), and conformed dimensions. Understand star schema (denormalized for query performance) vs snowflake schema (more normalized but requires more joins). For mid-level engineers, be able to design dimensional models for various business domains, understand the trade-offs between normalization and performance, and implement SCD logic appropriately.
Practice Interview
Study Questions
Complex SQL: Window Functions, CTEs, and Advanced Queries
Write sophisticated SQL queries for analytics: cumulative aggregations, running averages, ranking, cohort analysis, and time-series analysis using window functions (PARTITION BY, ORDER BY, ROWS/RANGE frames). Use Common Table Expressions (CTEs) for readability and complex query construction. Combine multiple techniques: multi-level aggregations, self-joins, complex WHERE conditions. For mid-level candidates, write SQL that is both correct and readable. Optimize for performance when needed, but prioritize clarity.
Practice Interview
Study Questions
Onsite Bar Raiser Round
What to Expect
This specialized round (typically 60 minutes) is conducted by a senior Amazon leader who acts as a 'Bar Raiser'—evaluating whether you meet or exceed Amazon's high standards for the role and company. This round combines technical problem-solving with behavioral assessment. You may be presented with an ambiguous, open-ended problem that requires creative thinking, systems analysis, and decision-making under uncertainty. The Bar Raiser assesses your technical depth, judgment, ability to handle ambiguity, and alignment with Amazon's leadership principles. Unlike other technical rounds that have clear right answers, the Bar Raiser round often has trade-offs and requires you to make reasonable decisions and defend them. You'll also be evaluated on communication clarity, intellectual curiosity, and critical thinking.
Tips & Advice
Expect challenging, open-ended questions that don't have single correct answers. Examples: 'How would you redesign Amazon's data infrastructure?' or 'If you inherited a poorly designed data pipeline in production, how would you approach fixing it?' Take time to understand the problem before jumping to solutions. Ask clarifying questions and make reasonable assumptions—state them explicitly. For mid-level candidates, demonstrate systems thinking: consider trade-offs, discuss multiple approaches, and justify your recommendations. Show intellectual humility—acknowledge limitations in your knowledge and areas where you'd want to learn more. Demonstrate curiosity: ask the interviewer follow-up questions about their challenges. Connect your thinking to Amazon's leadership principles, especially 'Invent and Simplify,' 'Are Right, a Lot,' and 'Deliver Results.' Be prepared to defend your position when challenged, but remain open to different perspectives.
Focus Topics
Cross-Functional Thinking and Communication
Data Engineers work with data scientists, analysts, product managers, and operations teams. Demonstrate ability to understand different perspectives, communicate technical concepts clearly to non-technical stakeholders, and find solutions that work for multiple teams. For mid-level candidates, discuss examples where you collaborated across functions and show ability to translate between technical and business languages.
Practice Interview
Study Questions
Technical Depth and Continuous Learning
Demonstrate deep expertise in your core areas (data engineering) while showing breadth across related domains. Be comfortable saying 'I don't know, but here's how I'd approach learning it.' Share examples of problems you've solved, skills you've developed, and how you stay current with technology changes. For mid-level candidates, discuss how you've grown technically and mentored others, showing investment in both your development and your team's.
Practice Interview
Study Questions
Amazon Leadership Principles Application
Understand Amazon's 16 Leadership Principles deeply, especially: Customer Obsession, Invent and Simplify, Are Right, a Lot, Learn and Be Curious, Deliver Results, Have Backbone; Disagree and Commit, Earn Trust, Think Big, Bias for Action, Frugality, Ownership. In the Bar Raiser round, demonstrate these principles through your problem-solving approach, examples from past work, and how you make decisions. For mid-level candidates, show not just understanding but embodiment of these principles.
Practice Interview
Study Questions
Problem-Solving Under Ambiguity
Handle open-ended problems gracefully. Break ambiguous problems into components. Make reasonable assumptions and state them clearly. Gather more information through questions. Propose a solution framework even if you don't have all details. For mid-level candidates, demonstrate comfort with ambiguity and ability to move forward with incomplete information—a key skill for owning medium-sized projects.
Practice Interview
Study Questions
Systems Thinking and Trade-Off Analysis
Approach problems holistically, considering multiple dimensions: performance, scalability, cost, reliability, maintainability, and team capability. When proposing a solution, articulate the trade-offs: what are the pros and cons of this approach compared to alternatives? For mid-level candidates, demonstrate mature judgment in making trade-off decisions based on context and requirements. Show understanding that 'best' depends on constraints and priorities.
Practice Interview
Study Questions
Onsite Behavioral and Leadership Principles Round
What to Expect
This final round (typically 45-60 minutes) with an HR representative or senior team member assesses your cultural fit, communication skills, and alignment with Amazon's leadership principles. Unlike technical rounds, this round focuses entirely on your past experiences, how you work with others, and whether you embody Amazon's values. You'll be asked behavioral questions about challenges you've faced, how you've handled conflicts, examples of innovation, failures and how you learned from them, and situations where you demonstrated Amazon's leadership principles. The interviewer is looking for candidates who are not just technically skilled but also collaborative, customer-focused, and driven by impact.
Tips & Advice
Prepare 5-7 specific examples from your past work that illustrate different Amazon Leadership Principles. Use the STAR method (Situation, Task, Action, Result) to structure your answers. Be concise initially, but be ready to elaborate with specific details when asked. Include quantifiable results when possible (e.g., 'reduced query time by 40%' or 'onboarded 3 junior engineers'). For mid-level candidates, prepare examples that show project ownership, mentorship, collaboration, and driving results through others. Be genuine—don't memorize scripts. Show vulnerability by discussing failures and what you learned. Ask thoughtful questions about the team's culture, challenges, and opportunities. Emphasize how you've grown from entry-level to mid-level and how you envision contributing to and learning from the Amazon culture.
Focus Topics
Collaboration and Communication
Share examples of successful collaborations with cross-functional teams (data scientists, product, operations). Discuss how you handle disagreements or conflicting priorities. For mid-level candidates, show examples of facilitating alignment between different teams and communicating technical concepts to non-technical audiences. Prepare an example of a time you received critical feedback and how you responded constructively.
Practice Interview
Study Questions
Amazon Leadership Principle: Deliver Results
Prepare examples of situations where you met or exceeded expectations despite challenges. Discuss your approach to prioritization, managing timelines, and handling blockers. For mid-level candidates, share examples where you drove team results, not just individual accomplishments. Include times you had to make tough trade-offs to ship on time.
Practice Interview
Study Questions
Growth, Learning, and Mentorship
Discuss your career growth from junior to mid-level roles. Share specific skills you've developed and how you've sought opportunities to learn. For mid-level candidates, prepare examples of mentoring junior colleagues or helping others grow. Discuss your approach to continuous learning and staying current with technology trends. Share an example of a mistake you made, what you learned, and how you applied that learning.
Practice Interview
Study Questions
Amazon Leadership Principle: Customer Obsession
Share examples of how you've prioritized customer needs in your work—this could mean end-users, internal customers (data scientists, analysts), or the business. Discuss how you've gathered customer feedback and incorporated it into your work. For mid-level engineers, show understanding that data engineering is ultimately in service of enabling better decisions and outcomes for customers, whether internal or external.
Practice Interview
Study Questions
Amazon Leadership Principle: Ownership and Invent and Simplify
Prepare specific examples of projects you owned end-to-end, from conception to delivery. Discuss a time you identified an inefficient process and simplified it. Show examples of how you took initiative without being asked. For mid-level engineers, demonstrate accountability not just for your own work but for your team's outcomes. Share a story where you drove innovation or challenged the status quo constructively.
Practice Interview
Study Questions
Frequently Asked Data Engineer Interview Questions
You have been asked to estimate a cost or capacity number, but the one input that actually drives it is a complete unknown, described only in vague, non-numeric terms rather than given as a number. Walk through how you would produce an initial estimate anyway: the assumptions you would state explicitly, a low, likely, and high scenario range built from those assumptions, and how you would present the range, with mitigation options, to the people who have to act on it, plus how you would validate your assumptions after the fact.
Sample Answer
When the one input that actually drives a cost or capacity number is described only in vague, qualitative terms, the first move is not to guess a number. It is to translate the vague description into the smallest concrete, measurable proxy question you can actually put numbers on, then bound that.
State the assumptions explicitly. Name the vague driver in plain language, then convert it into a numeric proxy and say out loud that the conversion itself is a judgment call. For example, if the driver is described as "some enterprise customers will want single sign-on (SSO, letting users log in through their company's existing identity system instead of a separate password)," the proxy question becomes "what fraction of the active deal pipeline, by count, will require SSO before signing." That translation is assumption number one.
Build a low, likely, and high range. Anchor each end to a named comparable, not a gut-feel spread: a low bound from the most conservative comparable available, a likely case from your best single proxy source, and a high bound from the most aggressive plausible comparable. Keep every number in the range on the same basis (same unit, same time window) so the three are actually comparable.
Alternate, fast approach worth knowing. When there is no time to build the full range, a deliberately low-confidence, fast, sampling-based method works: pull a small real sample right now (for example, contact 8 to 10 of the accounts in question this week) and use that raw hit rate as a bound, explicitly labeled as low-confidence and fast. The point of this version is specifically to give leadership something to make a go, no-go, or mitigation call on today, not to be treated as a final number; it trades precision for speed on purpose.
Present the range with mitigation options, not the range alone. Tie a concrete mitigation to each end: "if it lands at the high end, we buy a vendor SSO integration rather than build one; if it lands at the low end, we defer it entirely."
Validate afterward. Before you see the outcome, state what evidence, by what date, would confirm or reject each scenario, then actually go collect it.
Worked example. A team is asked to size infrastructure spend for a new self-serve pricing tier. The key driver, described only as "we think it'll be pretty popular, similar to a competitor's free tier," has no number attached. Proxy translation: percentage of monthly free signups converting to paid within 30 days. Basis for the range below: percent of free signups per month. Low: 2% (conservative end of published benchmarks for adjacent business-to-business software categories). Likely: 4% (informal comparison to the referenced competitor's stated conversion, adjusted down for a smaller brand). High: 7% (optimistic case if the competitor's figure is directly representative).
With 10,000 expected free signups per month (basis: signups/month), that converts to 200, 400, and 700 paid conversions per month respectively. At a marginal infrastructure cost of $3 per paid user per month (basis: dollars per paid user per month, not annualized, to avoid mixing a monthly rate with an annual one), monthly infrastructure cost bands are $600, $1,200, and $2,100. Mitigation tied to the range: at the high end, pre-provision autoscaling headroom to 800 users before it is needed; at the low end, hold off on a dedicated onboarding hire. Validation: at day 30, pull the actual conversion rate for that signup cohort; landing outside the low-high band is itself the signal that the "pretty popular" driver needs to be re-estimated from real data, not re-guessed.
A different-discipline version, briefly. A product manager is asked to estimate the cost of context-switching a proposed team restructure will cause, described only as "it'll probably slow things down for a bit." Proxy: expected percentage drop in delivered story points per sprint in the first month. Low 5%, likely 15%, high 30%, drawn from any comparable prior reorganizations, presented with a mitigation (staggering the change across two sprints instead of one) tied to the high end.
The trap. Naming a single confident percentage ("conversion will be about 4%") without disclosing that it is a proxy translation of a qualitative guess launders a guess into false precision, and nobody downstream knows they need to sanity-check it later.
You are given a denormalized 'orders' table in PostgreSQL with this shape:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
order_number TEXT,
customer_name TEXT,
customer_email TEXT,
shipping_address TEXT,
item_ids TEXT, -- comma-separated product ids
item_quantities TEXT, -- comma-separated quantities
total_amount NUMERIC(10,2),
created_at TIMESTAMP
);
The item_ids and item_quantities columns are comma-separated lists. Normalize this into a 3NF relational schema and provide the PostgreSQL CREATE TABLE statements for the normalized design. Explain the keys, constraints, and indexes you would use.
Sample Answer
Direct answer
The comma-separated item_ids/item_quantities columns are a repeating-group violation of 1NF; the fix is a proper order_items child table with one row per line item, each referencing the parent order and the product it represents.
Structured elaboration
-- Original (given): a 1NF violation via comma-separated lists in a single column
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
order_number TEXT,
customer_name TEXT,
customer_email TEXT,
shipping_address TEXT,
item_ids TEXT, -- comma-separated product ids
item_quantities TEXT, -- comma-separated quantities
total_amount NUMERIC(10,2),
created_at TIMESTAMP
);
-- Normalized 3NF design
CREATE TABLE customers (
customer_id BIGINT PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE
);
CREATE TABLE orders (
order_id BIGINT PRIMARY KEY,
order_number TEXT NOT NULL UNIQUE,
customer_id BIGINT NOT NULL REFERENCES customers(customer_id),
shipping_address TEXT NOT NULL,
total_amount NUMERIC(10,2) NOT NULL,
created_at TIMESTAMP NOT NULL
);
CREATE TABLE order_items (
order_item_id BIGINT PRIMARY KEY,
order_id BIGINT NOT NULL REFERENCES orders(order_id),
product_id BIGINT NOT NULL,
quantity INT NOT NULL,
UNIQUE (order_id, product_id)
);
CREATE INDEX idx_order_items_order ON order_items (order_id);
customer_name/customer_email are split into their own customers table for the same reason as any transitive dependency (they depend on the customer, not the order); item_ids/item_quantities become order_items, one row per line item, which is the direct fix for the repeating-group/1NF violation. UNIQUE(order_id, product_id) prevents the same product from silently appearing twice as two separate line items on one order (unless the business genuinely allows that, in which case a surrogate key without that constraint would be the right call instead).
Worked example
Verified in sqlite3: parsing a sample original row (item_ids='7,12,7', item_quantities='2,1,3', a deliberately tricky case with a duplicate product id 7 appearing twice) into the normalized form correctly requires SUMMING the quantities for the repeated product_id (7: 2+3=5, 12: 1) if the target order_items table has UNIQUE(order_id, product_id), since the original comma-separated data allowed the same product to appear twice with no way to distinguish "two separate line items" from "a data-entry duplicate meaning one combined quantity" without a business rule; this ambiguity in the SOURCE data is exactly the kind of problem a properly normalized schema (one row per distinct product per order, quantity as its own column) prevents from recurring going forward, even though migrating the messy historical data requires making an explicit decision about how to resolve it.
Trade-offs and pitfalls
- The migration from the old comma-separated format to the new normalized table is not purely mechanical when the source data itself is ambiguous (as the duplicate-product-id case above shows); a straightforward split-and-insert script would either fail the new UNIQUE constraint or silently produce two conflicting rows, so the migration needs an explicit decision (sum, keep-latest, or flag-for-review) for any such conflict found in the historical data, not just for going-forward writes.
- Parsing comma-separated values assumes a fixed, simple delimiter with no escaping needed; if any product-related text ever legitimately contained a comma (unlikely for numeric IDs, but a real risk if this anti-pattern were ever applied to text fields), the split-based migration would corrupt data silently rather than failing loudly.
- Once normalized,
order_itemsstill needs the same historical-price consideration discussed for other order-line-item designs: ifquantityis the only line-item-specific fact captured here, a later price change to the product would not retroactively affect this order (since price isn't stored per line), but if unit price at time of purchase needs to be preserved too, it belongs onorder_itemsdirectly, not looked up from a liveproductstable at read time.
Given an employees table with employee_id, manager_id, and name, write a recursive CTE that returns each employee's full reporting chain up to the top, as a path string like 'CEO > VP > Manager > Employee' along with the depth. Cap the traversal at a reasonable max depth and make sure a bad manager_id cycle in the data can't send it into an infinite loop.
Sample Answer
Direct answer: Start the recursion at the leaf (the employee whose chain you want), climb to their manager one join at a time, and stop when either the manager chain runs out (reached the top), a depth cap is hit, or a manager id you've already visited on this path shows up again. A recursive common table expression (CTE), written with WITH RECURSIVE, has two parts: an anchor query that seeds the starting rows, and a recursive term that repeatedly joins the CTE back to the base table until nothing new is produced or a stopping condition fires.
Approach
Anchor at every employee; recursive term joins to that employee's manager, prepending the manager's name to build the path and appending the manager's id to a visited-id array to guard against cycles.
WITH RECURSIVE reporting_chain AS (
-- anchor: every employee starts as their own chain of length 1
SELECT
employee_id AS start_id,
employee_id,
manager_id,
name::VARCHAR AS path,
1 AS depth,
ARRAY[employee_id] AS visited
FROM employees
UNION ALL
-- recursive term: climb one level to the manager, prepend their name
SELECT
rc.start_id,
m.employee_id,
m.manager_id,
m.name || ' > ' || rc.path,
rc.depth + 1,
rc.visited || m.employee_id
FROM reporting_chain rc
JOIN employees m ON m.employee_id = rc.manager_id
WHERE rc.depth < 10 -- depth cap
AND NOT (m.employee_id = ANY (rc.visited)) -- cycle guard
),
final_chain AS (
SELECT start_id, path, depth,
ROW_NUMBER() OVER (PARTITION BY start_id ORDER BY depth DESC) AS rn
FROM reporting_chain
)
SELECT start_id AS employee_id, path AS reporting_path, depth
FROM final_chain
WHERE rn = 1
ORDER BY employee_id;
Key points
UNION ALL, notUNION: the recursive term is expected to keep producing new (start_id, employee_id) pairs at increasing depth;UNIONwould force a distinctness check across every column on every iteration, which is both unnecessary (the visited-array guard already prevents true infinite loops) and expensive.- The depth cap (
rc.depth < 10) belongs in the recursive term'sWHERE, not as a post-hocLIMIT, becauseLIMITon the final result doesn't stop the recursion itself from running arbitrarily deep first. ROW_NUMBER() ... ORDER BY depth DESC, filtered torn = 1, picks each employee's longest (i.e., most complete) chain out of the intermediate partial chains the recursion necessarily also produces along the way.- PostgreSQL requires the
RECURSIVEkeyword (WITH RECURSIVE); SQL Server'sWITHdoes not use it at all, so this exact syntax is not portable as written across those two engines.
Worked example
Employees: (1, NULL, 'CEO'), (2, 1, 'VP'), (3, 2, 'Manager'), (4, 3, 'Employee').
Verified in PostgreSQL, the query returns:
| employee_id | reporting_path | depth |
|---|---|---|
| 1 | CEO | 1 |
| 2 | CEO > VP | 2 |
| 3 | CEO > VP > Manager | 3 |
| 4 | CEO > VP > Manager > Employee | 4 |
Employee 4's path matches the target string exactly: CEO > VP > Manager > Employee.
graph TD
CEO --> VP
VP --> Manager
Manager --> Employee
Complexity
Each recursive step is a join from the current frontier of rows back to employees on manager_id; with an index on employees(manager_id) (or the id used to join upward), each step costs proportional to the number of rows at that depth. Overall cost is bounded by (number of employees) x (average chain depth), since in a genuine org chart every employee contributes exactly one row per depth level of their own chain; the depth cap turns a potential unbounded cost into a hard ceiling regardless of how deep or malformed the underlying data is.
Edge cases
- Cycle in the data (e.g., a bad edit makes employee A report to employee B who reports back to A): verified by testing with (2,3,'Alice'), (3,2,'Bob'), (4,2,'Carl') as the sole rows. The recursion for employee 4 produces depth-1 through depth-3 rows and then correctly stops itself once climbing from manager 3 would revisit employee 2, which is already in the
visitedarray; it never reaches the depth-10 cap and never loops. - A chain longer than the depth cap: silently truncated at 10 levels; if that's a real risk in your org data, surface a flag on rows that hit the cap rather than letting a truncated chain look identical to a genuinely complete one.
- An employee with
manager_id IS NULL(the CEO): the anchor row for such an employee is already their complete, correct one-row chain; the recursive term simply never matches for them since there's no manager row to join to. - If the target engine lacks array types, substitute a delimiter-separated string for
visitedand check membership with aLIKEpattern (e.g.,'|' || rc.visited || '|' LIKE '%|' || m.employee_id || '|%'); it's less type-safe than an array but portable to engines without array support.
Trade-offs & pitfalls
The same shape, sometimes named level or distance from root instead of depth, and sometimes carrying an extra manager_name column pulled straight off each recursive step rather than folded into a path string, shows up repeatedly as the standard org-chart interview pattern; the depth counter, cycle guard, and anchor-plus-recursive-term structure are the substance being tested, the exact column names are cosmetic. For a hierarchy that's queried often but changes rarely (an org chart isn't restructured every minute), consider materializing the flattened chain into a table refreshed on a schedule or on write, rather than recomputing this recursive CTE on every dashboard load.
You maintain a Lambda architecture (separate batch and stream code paths). Provide a step-by-step migration plan to Kappa (a single streaming-based codepath with replay): code refactoring, state migration, reprocessing/backfill plan, tests to ensure parity with the old outputs, and a rollback strategy. What are the main risks, and how do you mitigate each?
Sample Answer
Direct answer
Migrating from Lambda to Kappa is fundamentally a data-parity project before it's an infrastructure project: the risk isn't standing up a streaming job, it's proving the new single codepath reproduces what the old batch layer was producing, for both live and replayed data, before you retire the batch layer that's been your correctness backstop.
Structured elaboration
Code refactoring: consolidate the batch and speed layer's business logic into one streaming-native implementation. In practice this usually means porting whatever the batch layer does (often SQL or a Spark job) into the stream processor's semantics (windowing, watermarks, state), which is where subtle behavior changes creep in, since "the same aggregation" can mean something different once you have to define how long to wait for late data.
State migration: any state the batch layer implicitly held (via full recompute each run) has to become explicit, durable, checkpointed state in the streaming job. Size this carefully; a batch job that scanned petabytes of history each run was never a good model for what needs to live in a stream processor's state store going forward, so decide what recent window actually needs to be live state versus what can be queried from cold storage.
Reprocessing/backfill plan: this is Kappa's whole value proposition, so prove it works before cutover. Pick a historical window, replay it through the new streaming job from the durable log, and confirm the output matches the old Lambda system's recorded output for that same window, not just that it runs without errors.
Parity tests: run the new Kappa pipeline in shadow, consuming the same live traffic as the existing Lambda system, for long enough to see your full range of edge cases (month boundaries, late data, any known-tricky periods). Diff outputs field by field, not just at an aggregate level, since a matching daily total can hide compensating errors underneath.
Rollback strategy: keep the old Lambda pipeline (or at minimum its batch layer) running and untouched until the new system has passed parity for an agreed bake period, and keep the cutover reversible, meaning downstream consumers should be able to be pointed back at the old output source without a schema change.
Worked example
Suppose the Lambda system's batch layer computes 30-day rolling revenue by user cohort, and the new Kappa job needs to replicate that with event-time windowing and a watermark policy. The parity test replays the last 90 days through the new job and compares its 30-day rolling revenue against the historical batch output, cohort by cohort. If the new job matches on 995 of 1,000 sampled cohort-days and the 5 mismatches all trace to one edge case (users who churned and re-signed up within the window), that's a concrete, fixable code bug (not a shrug-and-ship situation) found before cutover instead of in production.
Trade-offs and pitfalls
The main risk across all of this is declaring victory on aggregate-level parity ("the daily total matches") without checking finer granularity, since two wrong numbers can cancel out. The second risk is under-provisioning replay capacity: if replaying a full backfill window takes days instead of hours because the new streaming engine's state store or checkpointing wasn't sized for a large backfill, you've quietly recreated a batch job's latency inside a system that was supposed to make backfills fast. The third, org-level risk is retiring the old batch layer too early under pressure to "finish the migration"; keep it as a fallback until the new system has survived at least one real edge case (a late-arriving correction, a schema change) in production, not just in the parity test.
You notice your team and a neighboring team both think they own the same piece of a shared system, and the overlap is causing duplicated work and confusion about who's responsible for what. How do you sort out the ownership question and keep it from recurring?
Sample Answer
Direct answer
Get both teams in the same room with concrete evidence of the overlap, not each team's assumption about who owns what, agree on a single ownership model for the disputed piece, write it down somewhere both teams will actually find later, and set a lightweight recurring check so the boundary does not quietly drift back into ambiguity.
Structured elaboration
Start with evidence, not opinion
Map the actual overlap: which capability, which parts of the system, which decisions each team has been making independently. A short, concrete inventory, such as "both teams modified this component in the last quarter, for these reasons," turns a "whose job is this" argument into a shared problem to solve.
Choose an ownership model, do not just split the difference
Common options: one team owns it fully and the other is a client of it, ownership is split along a clear seam such as by data domain or by interface, or the piece gets consolidated into a single shared service with one clear owner. Whichever you pick, the test is whether a new engineer joining either team could read the agreement and know who to ask.
Write it down where it will be found
A decision made in a meeting and never documented decays within a sprint. Put the ownership boundary in the same place engineers already look, such as a README, a service catalog, or an API contract doc, not a one-off meeting note.
Set a recurring, lightweight check
A short standing sync between the two teams for boundary-crossing changes, or a simple rule that any change to the shared piece pings both teams, is enough to catch drift early without adding heavy process.
Worked example
Two teams both maintain code that retries failed requests to a downstream service, each having added its own retry and backoff logic independently over time. The overlap surfaces when a production incident review shows both teams' logic firing on the same failure and compounding retry pressure on the downstream service.
The teams map the overlap and find one team's logic lives in a shared client library, while the other's is inline in their own service and duplicates the same behavior. They agree the shared library should be the single source of retry logic, with the other team's inline logic removed and replaced by a call to the library. They write this into the library's README as "owned by Team A, changes to retry behavior require a ping in the shared channel," and add a short section to each team's onboarding doc pointing new engineers at the library first. They also add a lightweight rule: any pull request touching retry or backoff logic in either codebase gets a reviewer from the other team tagged automatically.
Trade-offs and pitfalls
Consolidating too aggressively can overstep a team's actual mandate and create a bottleneck if the new sole owner becomes a blocker for changes the other team needs quickly. Splitting too finely, dividing by an overly granular seam, creates new edge cases at the new boundary instead of removing them.
The common failure mode is not picking the wrong model, it is skipping the documentation and recurring-check steps because the meeting felt like it resolved things. Verbal agreements between the two people in the room do not survive a reorg or a new hire; only a written, discoverable agreement does.
You observe gradients near zero in a network's early layers and unusually large gradients in later layers (a vanishing/exploding gradient pattern). Walk through a systematic debugging and mitigation plan: which initialization schemes, normalization layers, residual connections, activation choices, and learning-rate strategies you would try, and what experiment you would run after each change to confirm it actually restored healthy gradient flow rather than just changing the symptom.
Sample Answer
Direct answer. Gradients near zero in the early layers and unusually large gradients in the later layers is the classic vanishing/exploding gradient signature: as the error signal is multiplied backward through many layers, repeated multiplication by weight matrices and activation derivatives either shrinks it toward zero or blows it up, and which one happens (or both, in different parts of the network) depends on the scale of the weights and the choice of activation function at each layer.
Systematic plan, in the order I'd actually try things.
- Check initialization first, it's the cheapest fix and the most common root cause. If weights are initialized with a fixed small variance regardless of layer width, deep networks will systematically shrink activations layer over layer. A variance-scaled scheme is one whose initial weight variance depends on the layer's width rather than on a constant you picked: He (Kaiming) initialization draws weights with variance
2/fan_in, where fan_in is the number of inputs to that layer and the factor of 2 compensates for ReLU zeroing out roughly half of its inputs; Xavier/Glorot uses2/(fan_in + fan_out), which balances keeping the forward activation variance stable against keeping the backward gradient variance stable, and is the right compromise for activations that behave roughly linearly near zero. So: He for ReLU-family activations, Xavier/Glorot for tanh/sigmoid, and the reason is the activation's effect on signal variance, not convention. - Check activation choice. Sigmoid and tanh saturate for large or small inputs, and their derivative in the saturated region is close to zero, which is a direct cause of vanishing gradients in deep networks. If you're using them in every hidden layer, swapping the hidden layers to ReLU or a variant removes an entire class of the problem, though it can introduce dead units instead. A dead unit is a ReLU whose input is negative for every example in the data: its output is always zero, so its gradient is always zero, so its weights never update again and it stays dead permanently. Leaky ReLU addresses this by giving the negative side a small nonzero slope instead of a flat zero; GELU addresses it by being smooth everywhere, scaling each input by roughly the probability that a standard normal draw falls below it, so there is no hard flat region for a unit to get stuck in.
- Add normalization layers. BatchNorm or LayerNorm re-centers and rescales activations between layers, which keeps the input distribution to each layer in a numerically well-behaved range regardless of what happened in the layers before it; this is often the single highest-leverage fix for genuinely deep networks.
- Add residual (skip) connections if the architecture allows it. A residual connection gives the gradient a path directly back to earlier layers that doesn't require it to survive a long product of derivatives, which is precisely why very deep architectures (ResNets, Transformers) rely on them rather than on initialization and normalization alone.
- Only after 1-4, tune the learning-rate strategy, since a learning-rate change can mask the symptom without fixing the underlying gradient-scale problem, making it the wrong first lever to pull. The three levers here: warmup ramps the learning rate from near zero up to its target over the first few hundred or few thousand steps, so the very first updates cannot wreck a network whose gradient scales have not settled yet; a lower peak learning rate shrinks every update uniformly; per-layer learning rates give each layer (or block) its own rate, typically smaller where gradients are already large, which treats the symptom directly and is the most obviously cosmetic of the three.
Confirming each change actually worked, not just changed the symptom. After each change, log the per-layer gradient norm (not just the total loss) for a few hundred steps. Here is the experiment, small enough to run in a second, comparing the two profiles on a 12-layer stack of Linear(64, 64) with a batch of 256 and an MSE loss, reading the gradient norm of each layer's weight matrix at the first step. The seed is pinned, so these are the numbers you get too.
import torch, torch.nn as nn
def grad_norms(build):
torch.manual_seed(0) # pinned: these numbers are reproducible
x, y = torch.randn(256, 64), torch.randn(256, 64)
lins, forward = build()
loss = nn.functional.mse_loss(forward(x), y)
loss.backward()
return [L.weight.grad.norm().item() for L in lins]
def broken(): # sigmoid, fixed-variance init, no norm, no residual
lins = [nn.Linear(64, 64) for _ in range(12)]
for L in lins:
nn.init.normal_(L.weight, 0.0, 0.1); nn.init.zeros_(L.bias)
def fwd(h):
for L in lins: h = torch.sigmoid(L(h))
return h
return lins, fwd
def fixed(): # ReLU + He init + LayerNorm + residual
lins = [nn.Linear(64, 64) for _ in range(12)]
norms = [nn.LayerNorm(64) for _ in range(12)]
for L in lins:
nn.init.kaiming_normal_(L.weight, nonlinearity="relu"); nn.init.zeros_(L.bias)
def fwd(h):
for L, N in zip(lins, norms): h = h + torch.relu(N(L(h)))
return h
return lins, fwd
hdr = "%-8s %11s %11s %11s %11s %11s" % ("", "layer 1", "layer 4", "layer 8", "layer 12", "last/first")
print(hdr)
for name, build in (("broken", broken), ("fixed", fixed)):
g = grad_norms(build)
print("%-8s %11.3e %11.3e %11.3e %11.3e %11.2e"
% (name, g[0], g[3], g[7], g[11], g[11] / g[0]))
layer 1 layer 4 layer 8 layer 12 last/first
broken 4.317e-10 2.225e-07 1.708e-04 1.214e-01 2.81e+08
fixed 3.811e-01 9.093e-01 1.064e+00 1.408e+00 3.70e+00
That is the criterion made concrete. The broken profile spans about eight and a half orders of magnitude from the first layer to the last, and layer 1's gradient at 4.3e-10 is far below fp16's smallest representable magnitude of about 6e-08, so in mixed precision those weights would receive an update of exactly zero. The fixed profile spans a factor of 3.7, well inside one order of magnitude, which is what "similar order of magnitude" means in practice. A genuine fix moves the last/first ratio from something like 1e+08 down to single digits. A smoother loss curve with the same lopsided gradient-norm profile usually means you've just changed the effective learning rate, not fixed the underlying instability, and the problem will likely resurface at a different depth or with a different dataset.
One emergency mitigation if you need the job to keep running while you investigate properly: apply gradient clipping (cap the global gradient norm at a fixed threshold). It won't fix vanishing gradients and it only band-aids exploding ones, but it prevents a single bad step from destroying the model's weights while you work through the checklist above.
List common network and I/O bottlenecks you would expect in large-scale data pipelines. For each bottleneck describe how it typically manifests (symptoms), what telemetry signals would indicate it, and propose at least one practical mitigation strategy (infrastructure or application-level). Include examples such as small-message overhead, high egress, and high disk seek latency.
Sample Answer
Direct answer. In a large-scale data pipeline the network and I/O bottlenecks that show up over and over are: high disk seek latency on random reads, small-message/small-file overhead, network egress saturation (especially cross-region), and consumer/producer imbalance that manifests as growing lag rather than a hard failure. Each has a distinct symptom signature, so the fastest diagnosis path is matching the symptom pattern to the mechanism before reaching for a fix.
Structured elaboration.
| Bottleneck | How it manifests | Telemetry signal | Practical mitigation |
|---|---|---|---|
| Small-message / small-file overhead | Throughput plateaus well below theoretical link/disk bandwidth even though CPU is idle | High iops relative to bytes/sec; many small PUTs to object storage; per-record serialization overhead dominates | Batch records before write (micro-batching), compact small files after the fact, increase producer batch size |
| High network egress (cross-AZ/cross-region) | Latency climbs specifically on cross-boundary hops; same-zone paths stay fast | Egress byte counters spike; NIC saturation on specific hosts; cost anomaly on network line items | Co-locate producer/consumer where possible, compress before crossing the boundary, batch cross-region transfers |
| High disk seek latency (random I/O) | Reads are slow but writes (often sequential, e.g., a write-ahead log/commit-log -- an append-only file recording changes before they are applied) stay fast; worse on HDD-backed storage | Elevated iowait, high average seek time in disk metrics, low queue depth utilization despite high latency | Move hot data to SSD-backed storage, restructure access pattern to sequential (columnar/sorted layout), add a cache in front of the random-access path |
| Consumer/producer imbalance (backpressure building) | No single request is slow, but a queue or consumer-lag metric grows monotonically | Rising consumer lag / queue depth over time, NOT correlated with per-record latency | Scale consumers, or slow the producer via backpressure signaling (see the topic's backpressure staple) |
The key diagnostic habit: a bottleneck that shows up as elevated per-operation latency with the resource near saturation (disk iowait, NIC utilization) is a hardware/transport-layer problem you fix by reducing the work per operation or moving to faster media. A bottleneck that shows up as a growing queue with no individual operation looking slow is a rate-mismatch problem you fix with backpressure or added parallelism, not by making any one operation faster.
Worked example. A pipeline ingests 200,000 small JSON records/sec (about 300 bytes each) directly to object storage, one PUT per record. Raw byte throughput is only 200,000 x 300 bytes = 60 MB/sec, far under any reasonable network or storage ceiling, yet the pipeline falls behind. The signal here is that IOPS (200,000/sec) is the constraint, not bandwidth: object stores typically cap sustained PUT rates per prefix far below that. Batching records into 1 MB writes cuts the PUT rate: 60 MB/sec of throughput divided by 1 MB per batch requires 60 writes/sec, verified by direct division (60 MB/sec / 1 MB = 60), with no code change to the per-record logic -- a 200,000/60 ~= 3,333x reduction in request count for the same data volume. Sustaining 60 writes/sec means each batch fills in roughly 1/60 second (about 16.7ms) on average across the pipeline's writers, not a single slow 200ms-per-batch cadence.
Trade-offs & pitfalls. Batching to fix small-message overhead trades latency for throughput: a 200ms batching window adds up to 200ms of end-to-end delay per record. That is almost always the right trade at pipeline scale, but it is a real trade, not a free win, and should be sized against the pipeline's actual latency SLA rather than maximized blindly. The common mistake is chasing CPU metrics when the real constraint is IOPS or egress bandwidth; check the request-count and byte-count signals side by side before assuming a compute-bound problem.
Tell me about a time you had to escalate a stakeholder conflict to leadership because the people involved could not agree on priorities themselves. What made you decide to escalate rather than keep working it peer to peer, and how did you frame the ask to leadership?
Sample Answer
Direct answer
Escalating a stakeholder conflict to leadership is the right call when peer-level resolution has genuinely been tried and failed, the disagreement is actively blocking meaningful progress, and the decision at stake is significant or hard to reverse; framing the escalation as a request for a decision rather than a complaint about either party is what makes it land well.
Structured elaboration
- What made escalation the right call, not just an easier one. A real attempt at resolving the disagreement directly should precede escalation; the deciding factor is usually that continued peer-level effort was unlikely to converge and the cost of continued delay was rising.
- How the ask to leadership was framed. Presenting the situation neutrally, with both sides' reasoning represented fairly, and asking specifically for a decision on a defined question, rather than asking leadership to referee who's "right," keeps the conversation focused on unblocking progress.
- What leadership needed to make a good call. A concise summary of the disagreement, what was tried, the trade-offs of each option, and a clear ask (a decision, a resource, an explicit priority call) gives leadership what they need without requiring them to relitigate the whole history.
- What happened afterward. Documenting the resolution and communicating it back to both original parties closes the loop, so the escalation doesn't leave lingering resentment about how it was handled.
Worked example
Two teams couldn't agree on which of two conflicting priorities to pursue with shared, limited resources, and each had reasonable grounds for their position. After a joint conversation failed to converge over several days while the clock on both timelines kept running, escalating with a short written summary presenting both positions fairly, the trade-offs of each, and an explicit request for a priority call, let leadership make a fast, informed decision rather than re-litigating the underlying technical debate themselves.
Trade-offs and pitfalls
An escalation framed even slightly as blame-assigning, rather than decision-seeking, tends to put leadership in the position of managing your relationship with the other party instead of making the actual call needed, which is a worse outcome for everyone involved.
Your request path chains three components in series, each sitting at 99.9% availability on its own. How does that combine into your end-to-end availability, and if the SLA actually requires 99.99%, what would you be willing to spend to close that gap?
Sample Answer
Direct answer
For three components in series, end-to-end availability is the product of the individual availabilities, so 99.9% x 99.9% x 99.9% is well below 99.9% overall, since every additional serial link can only make things worse, never better. Closing the gap to a 99.99% service-level agreement (SLA) target costs money in redundancy, and how much you're willing to spend depends on the business cost of the downtime you're trying to eliminate versus the cost of the additional infrastructure and operational complexity redundancy requires.
Structured elaboration
For independent components A, B, C in series, the system availability is:
Asys=A×B×C
If all three sit at 99.9% (0.999) individually:
Asys=0.9993≈0.997→99.7%
that's a meaningfully worse number than any single component's own 99.9%, which is the core insight: serial dependencies compound failure probability, they don't average it.
To hit 99.99% with identical components and no redundancy, each component alone would need to reach:
p=(0.9999)1/3≈0.999967→99.9967% per component
That's a very high bar for a single component to hit on its own. The more common and often cheaper path is redundancy: for n independent replicas of a component each at availability p:
Acluster=1−(1−p)n
With p=0.999 (the original 99.9% component) and n=2 replicas:
Acluster=1−(0.001)2=0.999999→99.9999%
Replacing all three serial components with a 2-replica redundant cluster each gives:
Asys=(0.999999)3≈0.999997→99.9997%
well above the 99.99% target, using only 2x redundancy per component rather than pushing any single component to a much harder 99.9967% target.
Worked example
Translating these percentages into downtime budgets makes the trade-off concrete. At the original 99.99% target:
downtime at 99.99%/year=(1−0.9999)×525,600 min≈52.6 min/year
At the redundancy-based 99.9997% actually achieved above:
downtime at 99.9997%/year≈(1−0.999997)×525,600 min≈1.6 min/year
So 2x redundancy per component doesn't just meet the 99.99% SLA, it clears it with roughly 51 fewer minutes of annual downtime budget spent. That headroom is what you'd spend, or not spend, depending on the actual cost of an outage minute to the business: if an outage minute costs far less than the added infrastructure and on-call complexity of running every component as an active redundant pair, the cheaper path might be accepting the tighter 99.99% target with only one component redundant, not all three.
Trade-offs & pitfalls
- The multiplicative model assumes independent failures; shared infrastructure (the same power feed, the same network path, the same region) breaks that independence, and correlated failures can quietly undermine a redundancy plan that looks solid on paper.
- Redundancy only helps if failover is fast and reliable; factoring in mean time to recovery (MTTR) alongside mean time between failures (MTBF) matters as much as the raw availability percentage.
- Don't over-invest in the component that's cheapest to make redundant if it isn't the actual constraint; prioritize redundancy where it buys the most availability per dollar, not where it's easiest to implement.
- A common shallow answer stops at "multiply the availabilities" without translating the result into a downtime budget and a cost decision; the interviewer is listening for the willingness-to-spend reasoning, not just the formula.
Design a pattern to implement cross-service consistency for an order-processing workflow that writes to an OLTP orders DB and also writes events to an analytics warehouse. Compare implementing distributed transactions (2PC) vs eventual consistency via SAGA or outbox + CDC. Consider failure modes, latency, and developer experience.
Sample Answer
Requirements & constraints:
- Strong consistency between OLTP orders DB and analytics warehouse is desirable but not strictly required in real time.
- Scale: high write rate, multiple services, heterogeneous storage (RDBMS + data warehouse).
- Non-functional: availability, low operational complexity, recoverability, and auditability.
Option A — Distributed transactions (2PC):
- Approach: Use XA/2PC coordinator to atomically commit order write and event write across systems.
- Failure modes: coordinator single point of failure, locking in resource managers causing long-held DB locks, complex recovery when participants crash mid-commit. If the analytics system doesn’t support XA (common for warehouses), impossible.
- Latency: higher synchronous latencies because commit requires coordinator round-trips to all participants.
- Developer experience/ops: high cognitive and operational burden; brittle across heterogeneous systems; hard to scale across geo/managed services.
Option B — SAGA (orchestrated/choreographed):
- Approach: Break the workflow into compensatable steps (create order → publish event → update downstream). Orchestrator coordinates steps and compensations on failure.
- Failure modes: need reliable compensating actions; compensation complexity for side-effects (e.g., payments). Risk of temporary inconsistencies until saga completes.
- Latency: lower per-step latency; end-to-end eventual consistency; depends on orchestration speed.
- Developer experience: requires modeling compensations and idempotent operations; moderate complexity but doable for business flows.
Option C — Outbox + CDC (recommended for this context):
- Approach: Write order row and an outbox event record in the same OLTP transaction. Use CDC (Debezium/Kafka Connect) or a background poller to stream outbox rows to Kafka and into the analytics warehouse (via streaming pipelines).
- Failure modes: simpler recovery model — if delivery fails, pipeline retries; need to ensure at-least-once delivery and idempotent consumers to avoid duplicates; careful schema evolution and retention.
- Latency: near-real-time (depends on CDC throughput and batch loads) with much lower OLTP latency than 2PC.
- Developer experience/ops: good balance — transactional atomicity on the OLTP side with standard streaming tooling; easier to monitor, replay, and audit; fewer cross-system locks; works well with warehouses (CDC → Kafka → transform → warehouse).
Comparison summary:
- Consistency: 2PC gives strong cross-system atomicity (if supported). Outbox+CDC and SAGA give eventual consistency but are observable and recoverable.
- Reliability & failure handling: Outbox+CDC is most operationally robust for heterogeneous stacks; SAGA works where compensations are straightforward. 2PC is fragile at scale.
- Latency: 2PC highest, SAGA/outbox lower; outbox+CDC offers best throughput with acceptable latency.
- Developer experience: Outbox+CDC lowest friction (transactional semantics remain local); SAGA requires business modeling; 2PC increases complexity and often impractical.
Recommendation:
For a data engineering context (OLTP orders DB + analytics warehouse), implement outbox + CDC streaming into your warehouse. Benefits: atomic writes on OLTP, scalable, observable pipelines, replayability for backfills, and easy integration with Kafka/Spark. Complement with idempotent consumers, monitoring for lag/errors, schema evolution policies, and retention/garbage-collection for outbox records. Use SAGA only for complex multi-service business transactions needing compensations; avoid 2PC except in tightly controlled homogeneous environments that fully support XA.
Recommended Additional Resources
- Amazon Careers Page - Data Engineer roles: amazon.jobs (official job postings and interview preparation resources)
- LeetCode and DataLeetCode: SQL and coding practice for technical interview preparation
- Blind and Levels.fyi: Community insights and recent interview experiences from Amazon candidates
- Glassdoor: Company reviews and interview process details from former and current Amazon employees
- Books: 'Designing Data-Intensive Applications' by Martin Kleppmann for data systems fundamentals, 'The Art of SQL' for advanced SQL techniques
- Apache Spark Documentation and Tutorials: Official Spark documentation for distributed computing framework understanding
- AWS Training and Certification: AWS Glue, Redshift, EMR, and S3 documentation for Amazon-specific data tools
- System Design Interview by Gaurav Sen (YouTube): System and architecture thinking for data pipeline design discussions
- Mock Interview Platforms: Pramp, Interviewing.io, or Exponent for practicing with real interviewers in mock settings
- Amazon Leadership Principles: Research and internalize all 16 principles, available on amazon.jobs/en/principles
Search Results
Amazon Data Engineer Interview Guide 2024 | Questions, Process
Read this comprehensive guide for valuable insights and tips to ace your Amazon data engineer interview with interview questions, process and timeline.
Amazon Data Engineer Interview in 2025 (Leaked Questions)
This comprehensive guide will provide you with insights into Amazon's interview process, the essential skills required, and strategies to help you excel.
The 2025 Amazon Data Engineer interview guide | Prepfully
Detailed, specific guidance on the Amazon Data Engineer interview process - with a breakdown of different stages and interview questions asked at each stage.
Amazon Data Engineer Interview (questions, process, prep)
We've put together the ultimate guide, complete with 50+ example questions and insider advice from our expert Amazon coaches Jitesh, Bilwasiva, and Dessy.
Interview preparation for data roles - Amazon.jobs
Interviews for Data Engineer and Business Intelligence Engineer roles assess your technical acumen through a combination of verbal and coding exercises.
Amazon Data Engineer Interview Guide | Sample Questions (2025)
Prepare for the Amazon Data Engineer interview with an inside look at the interview process and sample questions. Learn how to get a Data Engineer job at ...
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