Meta Site Reliability Engineer (Mid-Level) Interview Preparation Guide
While search results confirm that Meta conducts Site Reliability Engineer interviews, comprehensive details about Meta's official interview process structure, specific round sequence, and evaluation criteria were not available in the provided search results. This guide is based on industry-standard SRE interview practices at major tech companies and common interview patterns documented in community discussions. For the most current and accurate information, candidates are advised to consult Meta's official careers page, recent discussions on Levels.fyi and Blind, and feedback from recent interviewees.
Meta's Site Reliability Engineer interview process for mid-level candidates (2-5 years of experience) follows a comprehensive multi-stage evaluation designed to assess technical depth, systems thinking, operational knowledge, and cultural fit. The process combines initial recruiter engagement, technical phone screens evaluating coding and systems expertise, and intensive onsite interviews covering system design, advanced troubleshooting, coding problem-solving, and behavioral competencies. At mid-level, Meta evaluates your ability to own complex projects end-to-end, mentor junior colleagues, drive reliability improvements, and collaborate effectively across teams.
Interview Rounds
Recruiter Screening
What to Expect
Initial combined recruiter call covering both preliminary assessment and deeper background exploration. The recruiter reviews your resume, understands your career path, and assesses alignment with Meta's SRE role and team needs. They'll discuss your experience with system reliability, incident response, automation, and operational work. This is your opportunity to demonstrate genuine interest in Meta, understanding of the role's responsibilities, and enthusiasm for contributing to their infrastructure. The recruiter will also discuss logistics, compensation expectations, and answer initial questions about the team and role.
Tips & Advice
Research Meta's engineering culture, infrastructure scale (billions of users, global presence), and reliability challenges before the call. Prepare concise stories about your most impactful reliability projects—focus on business impact and what you learned. Articulate specifically why you're interested in Meta (beyond just the brand) and what attracted you to the SRE role. Be genuine and conversational; recruiters evaluate cultural fit and whether you'll thrive in Meta's environment. Ask thoughtful questions about the specific team, on-call rotation structure, incident response culture, and what success looks like in the role. Have your resume easily accessible and be ready to discuss specific technical decisions, challenges overcome, and metrics demonstrating your impact. If asked about salary expectations or current compensation, research market rates beforehand.
Focus Topics
Collaboration and cross-team communication
Provide examples of how you've worked effectively with product teams, backend/infrastructure teams, security teams, or other stakeholders. Discuss how you communicate about reliability tradeoffs, advocate for reliability investments, and handle situations where reliability and feature velocity conflict. Show that you're easy to work with and good at building relationships.
Practice Interview
Study Questions
Technical depth and relevant tool experience
Summarize your technical expertise: programming languages you're proficient in, monitoring and observability tools (Prometheus, Grafana, ELK, Datadog, etc.), container orchestration experience (Kubernetes, Docker), cloud platforms (AWS, GCP, Azure), automation frameworks, and incident response tooling. Be honest about your depth in each area—where are you expert, where are you competent, where are you still developing skills?
Practice Interview
Study Questions
Career motivation and Meta-specific interest
Articulate why you're interested in an SRE role and specifically why Meta attracts you. Demonstrate knowledge of Meta's scale (billions of users globally), technical challenges (maintaining reliability at scale, handling diverse platforms), and engineering culture. Connect your experience and goals to Meta's needs around building resilient, performant systems. Show you've thought about this opportunity seriously.
Practice Interview
Study Questions
Systems reliability improvements and measurable impact
Share 2-3 concrete examples of systems or services where you meaningfully improved reliability. For each, describe: the problem or gap you identified, your approach to solving it, what you implemented, and quantifiable results (e.g., reduced mean time to recovery by 60%, eliminated manual restarts, improved uptime from 99.5% to 99.95%, reduced on-call pages by 70%). This demonstrates your ability to deliver impact.
Practice Interview
Study Questions
Experience with incident response and on-call responsibilities
Prepare specific examples of incidents you've responded to: what failed, your role in diagnosis and resolution, timeline, and what you learned. Discuss your comfort with on-call rotations, pager duties, and emergency response. Explain your philosophy on balancing reactive incident response with proactive reliability improvements. Show that you understand on-call is challenging but essential to SRE work.
Practice Interview
Study Questions
Technical Phone Screen - Coding and Algorithms
What to Expect
First technical phone interview assessing your coding ability, algorithmic thinking, and problem-solving methodology. You'll work through one to two coding problems, typically at LeetCode medium difficulty or slightly harder, in a collaborative coding environment (Google Docs, CoderPad, or similar). Problems may include graph traversal, dynamic programming, data structure design, or optimization challenges. The interviewer evaluates your approach to problem-solving, code quality, ability to identify and handle edge cases, and capacity to optimize solutions. Communication and thinking aloud are as important as arriving at the correct answer.
Tips & Advice
Start by clarifying problem requirements and constraints before coding. State your assumptions and confirm them with the interviewer—this demonstrates systematic thinking. For each problem, briefly outline your approach and complexity analysis before writing code. Write clean, readable code with meaningful variable names and consistent indentation. Test your solution against provided examples and generate your own test cases, including edge cases (empty input, single element, large inputs, duplicates, boundary conditions). If you get stuck, explain your thinking and ask for hints rather than sitting silently. If you finish early, optimize your solution or discuss alternative approaches. For SRE-specific problems, expect scenarios around graph problems (network connectivity, dependency mapping), data structure design (metrics collection, time-windowed data), or practical problems around resource optimization. Be conversational; explain your reasoning as you code so the interviewer can follow your thought process and provide guidance if needed.
Focus Topics
Communication and collaboration during problem-solving
Verbalize your thinking as you solve problems. Explain your approach before coding. Ask clarifying questions. Accept feedback and adapt if the interviewer suggests an alternative direction. Show that you can work collaboratively and are open to learning from the interviewer.
Practice Interview
Study Questions
Edge case identification and thorough testing
Systematically think through edge cases: empty/null inputs, single elements, large inputs, duplicates, negative numbers, boundary conditions. Test your solution against these cases. This demonstrates that you think like a reliability engineer—you anticipate failure modes and guard against them.
Practice Interview
Study Questions
Code quality and production-readiness
Write code that's clean, readable, and maintainable. Use descriptive variable names, add comments where clarity isn't obvious, handle error cases, and follow consistent conventions. Avoid hacky shortcuts that work but are fragile. Demonstrate that you think about edge cases and robustness, not just happy-path functionality. This reflects your engineering discipline.
Practice Interview
Study Questions
Time and space complexity analysis
Deeply understand Big O notation and be able to analyze your solution's complexity. Discuss time-space tradeoffs. When asked to optimize, identify the bottleneck and explain how your optimization improves complexity. Show that you make conscious decisions about complexity, not just write code that happens to work.
Practice Interview
Study Questions
Algorithm design and problem-solving approach
Master ability to approach problems systematically: understand requirements, identify constraints, brainstorm approaches, evaluate tradeoffs, and implement efficiently. Practice LeetCode medium to hard problems focusing on graph traversal (BFS/DFS), dynamic programming, arrays, strings, trees, and sorting/searching. For SRE relevance, focus on problems that could appear in real systems (path finding, resource allocation, time-window queries).
Practice Interview
Study Questions
Technical Phone Screen - Systems and Operational Troubleshooting
What to Expect
Second technical phone interview focusing on systems knowledge, troubleshooting capabilities, and operational thinking. You'll face realistic scenarios where systems are experiencing problems—degraded latency, elevated error rates, resource exhaustion, connectivity issues, etc. Your task is to systematically diagnose the root cause and propose solutions. The interviewer evaluates your methodology, depth of systems knowledge, understanding of monitoring and observability, and ability to think through distributed system failure modes. This round directly assesses your core SRE competency: diagnosing and resolving production incidents.
Tips & Advice
Treat this like a real incident scenario. Start by clarifying symptoms, timeline, scope (which users/regions affected), and what monitoring/logs are available. Ask about recent changes, deployment history, traffic patterns, or dependency failures that might correlate. Propose a systematic troubleshooting approach: gather information, form hypotheses, test hypotheses, eliminate possibilities. Think out loud so the interviewer follows your reasoning. Be comfortable with Linux command-line tools and ask about tools you'd use to diagnose problems. Understand basic networking (DNS, routing, ports, connections) and how to debug connectivity issues. Discuss what metrics and logs would help you diagnose the problem. For distributed systems, consider failure modes at each layer: application, middleware, infrastructure, network. Show deep practical knowledge, not just theoretical understanding. If you don't know something, admit it and explain how you'd find the answer.
Focus Topics
Distributed system failure modes and resilience
Understand common failure patterns at scale: cascading failures, thundering herd, network partitions, resource exhaustion, retry storms, dependency failures. Discuss how systems can defend against these: circuit breakers, backpressure, graceful degradation, bulkheads. Think through how systems recover from partial outages. Understand eventual consistency and its implications.
Practice Interview
Study Questions
Networking concepts and connectivity troubleshooting
Understand DNS resolution, routing, TCP/IP fundamentals, ports, connections, firewalls, and load balancing. Troubleshoot connectivity issues using tools like ping, traceroute, telnet, nc, netstat, ss, ifconfig, ip, dig, nslookup, and tcpdump. Diagnose DNS failures, routing problems, port conflicts, and connection timeouts. Understand common network failure modes in distributed systems.
Practice Interview
Study Questions
Systematic incident diagnosis and root cause analysis
Master a structured troubleshooting methodology: (1) understand symptoms and timeline, (2) gather system state and metrics, (3) form hypotheses about root cause, (4) test hypotheses systematically, (5) identify true root cause, (6) implement solutions. Practice diagnosing realistic scenarios: latency spikes, error rate increases, resource exhaustion, cascading failures. Think through what information you'd need at each step.
Practice Interview
Study Questions
Linux systems and command-line diagnostics
Demonstrate deep proficiency with Linux systems: process management (ps, top, kill, pgrep), memory analysis (free, vmstat, ps), CPU analysis (top, mpstat, iostat), disk I/O (iostat, iotop, df, du), file systems, permissions, system calls (strace), and system logs (/var/log). Understand how to identify bottlenecks and interpret performance metrics. Be comfortable navigating systems and gathering diagnostic information efficiently.
Practice Interview
Study Questions
Monitoring interpretation and observability thinking
Understand what to monitor (SLIs like latency percentiles, error rate, throughput), how to interpret dashboards and metrics, and what signals indicate problems. Discuss alert design and how to avoid alert fatigue. Think about how to instrument systems for observability: what metrics, logs, and traces would help diagnose this problem? Understand correlation between metrics to identify root causes.
Practice Interview
Study Questions
Onsite Interview - System Design (Non-Abstract Large System Design)
What to Expect
Comprehensive system design interview emphasizing Non-Abstract Large System Design (NALSD)—designing systems that must actually work in production with operational realism. Unlike traditional system design focusing primarily on functional requirements and scalability, this round emphasizes operational concerns fundamental to SRE work: reliability and failure handling, deployment strategies, monitoring and alerting architecture, capacity planning, incident response procedures, and cost optimization. You'll design a complex system handling real-world constraints and prove you understand how to operate it. The interviewer expects you to incorporate observability, resilience, and operational simplicity into your design from the ground up.
Tips & Advice
Begin by clarifying requirements and constraints: QPS (queries per second), latency requirements, data volume, geographic distribution, consistency needs, availability targets (SLO/SLA), and cost constraints. Explicitly state assumptions and verify them with the interviewer. Design for failure from the start—discuss failure modes at each layer and how your system detects and recovers. Include monitoring and alerting in your design from the beginning, not as an afterthought. What metrics indicate health? What should trigger alerts? How will engineers understand what's happening? Discuss capacity planning: how will you predict resource needs and handle growth? Explain deployment strategies: canary deployments, gradual rollouts, rollback procedures, zero-downtime updates. For a mid-level SRE, operational concerns are as important as functional design. Draw clear diagrams showing architecture, data flow, and failure isolation. Discuss tradeoffs explicitly: strong vs. eventual consistency, synchronous vs. asynchronous, batch vs. real-time, centralized vs. distributed. Explain why you made specific architectural choices and what alternatives you considered. Be prepared to defend your choices and discuss different scenarios. Consider cost implications—at Meta's scale, small inefficiencies become huge costs.
Focus Topics
Architecture tradeoff analysis and decision-making
Explicitly discuss tradeoffs in your design: strong consistency vs. eventual consistency, synchronous vs. asynchronous communication, batch processing vs. real-time, centralized vs. distributed systems. Explain how you'd decide which approach fits the requirements. Discuss technology choices and their operational implications. Show that you can reason about architectural decisions and understand their downstream effects.
Practice Interview
Study Questions
Capacity planning, resource optimization, and growth handling
Estimate resource requirements based on scale requirements. How will you predict future capacity needs and plan for growth? Consider headroom and overprovisioning strategies. Discuss cost implications of your architectural choices. If appropriate, discuss auto-scaling: how does it work, what are its benefits and limitations? How do you test capacity planning before hitting limits in production?
Practice Interview
Study Questions
Designing for reliability and failure resilience
Incorporate redundancy, fault isolation, and graceful degradation throughout your design. For each component, discuss failure modes: what happens if it fails? Design detection mechanisms (health checks, timeouts, error rates). Design recovery strategies (retries with backoff, circuit breakers, bulkheads, failover). Discuss both single-region and multi-region architectures. Think about cascading failure prevention and how to limit blast radius of failures.
Practice Interview
Study Questions
Monitoring, observability, and alerting architecture
Incorporate observability into your design from the start. Define Service Level Indicators (SLIs) aligned with user-facing outcomes (e.g., successful requests, latency percentiles). Propose how you'd instrument the system: what metrics at each layer? What logs are important? How would you trace requests through the system? Design your alerting: what signals indicate problems? How do you avoid alert fatigue? How would you run post-mortems after incidents? Explain how an on-call engineer would understand and diagnose problems.
Practice Interview
Study Questions
Operational simplicity and deployment procedures
Design systems that are operationally maintainable and don't require heroic manual effort. Discuss how to deploy updates safely: blue-green deployments, canary deployments, rolling deployments. How do you roll back if deployment fails? How do you handle zero-downtime updates? What operational tasks are manual vs. automated? What could go wrong during deployment? How is the system operationally different from the design diagram—what challenges emerge in practice?
Practice Interview
Study Questions
Onsite Interview - Coding and Algorithms
What to Expect
Technical coding interview conducted during the onsite day, assessing your problem-solving ability, code quality, and technical thinking under interview pressure. You'll work through one to two coding problems, typically at LeetCode medium-hard difficulty, potentially with more depth or complexity than the phone screen. Problems may include algorithm optimization, data structure design, or practical scenarios relevant to systems work. The interviewer evaluates your problem-solving approach, code quality, ability to optimize and improve solutions, and communication during problem-solving. This round validates that your coding ability holds up under onsite interview conditions.
Tips & Advice
This round is similar in structure to the phone screen coding round but may involve slightly more complex problems or require deeper optimization. Be thorough and methodical. Start by fully understanding the problem before writing code. Think out loud so your interviewer can follow your reasoning and potentially offer guidance. Write clean code with good naming conventions and proper structure. Test your solution comprehensively with various test cases including edge cases. If you finish early or solve quickly, ask if the interviewer would like you to optimize further or solve additional problems. Stay calm and engaged if you get stuck—explain your thinking and work through the problem with the interviewer. Remember that your problem-solving process and communication are evaluated as much as your final solution. For SRE-specific problems, expect practical scenarios: optimizing data structures for high-throughput metrics collection, solving graph problems related to network topologies or dependency mapping, designing efficient algorithms for log processing or event correlation.
Focus Topics
Problem-solving communication and collaboration
Verbalize your thinking as you work. Explain your approach before coding. Discuss tradeoffs as you consider different solutions. Accept feedback and adapt if the interviewer suggests an alternative direction. Show intellectual humility by acknowledging uncertainty and openness to learning.
Practice Interview
Study Questions
Code quality, structure, and maintainability
Write production-quality code: proper error handling, edge case management, clear structure, and good naming. Code should be readable and maintainable, not clever. Add comments where helpful. Be able to trace through your code mentally and explain what it does. If the interviewer points out bugs, identify and fix them gracefully.
Practice Interview
Study Questions
Algorithm design for systems-relevant problems
Master algorithms commonly relevant to systems and SRE work: graph algorithms (BFS/DFS for dependency analysis and network routing), sorting and searching, dynamic programming for optimization, data structure design (e.g., designing efficient data structures for time-windowed metrics or event streams). Practice LeetCode medium to hard problems. Focus on problems that could realistically apply to SRE scenarios.
Practice Interview
Study Questions
Time and space complexity analysis and optimization
Deeply understand Big O notation and analyze your solution's complexity. Identify performance bottlenecks and understand how to optimize them. Discuss time-space tradeoffs and make conscious decisions about these tradeoffs. When asked to optimize, explain how your optimization improves complexity and what the new tradeoffs are. Show that you make deliberate decisions, not just write code that 'works.'
Practice Interview
Study Questions
Onsite Interview - Troubleshooting and Systems Deep Dive
What to Expect
Technical interview focusing on systems troubleshooting, operational knowledge, and your ability to handle production incidents under pressure. You'll face realistic scenarios where systems are degraded or failing (latency spikes, elevated error rates, resource exhaustion, cascading failures, etc.), and you need to diagnose root causes and propose solutions. This round is a direct assessment of your core SRE competency: handling production incidents. The interviewer evaluates how you ask questions, gather information, formulate hypotheses, eliminate possibilities systematically, identify root causes, and design solutions. This is where theory meets practice.
Tips & Advice
Treat this like a real incident scenario. Ask clarifying questions first: what symptoms are observed? When did it start? What's the scope (users, regions, services affected)? What changed recently? Gather information systematically: what do monitoring dashboards show? What do logs reveal? What resources are constrained? Work through hypotheses methodically—form a hypothesis, explain how you'd test it, and discuss what results would confirm or refute it. Show deep knowledge of Linux systems, networking, and operational concepts. Discuss what tools and information you'd use to diagnose problems. For a mid-level SRE, interviewers expect confidence and practical knowledge grounded in real experience. Acknowledge uncertainties honestly, but show your thought process for finding answers. Walk through your troubleshooting process so the interviewer can follow and potentially guide you toward the root cause if you're stuck.
Focus Topics
Monitoring data interpretation and alerting
Read and interpret monitoring dashboards and metrics effectively. Understand what different metrics indicate about system health. Discuss what information you'd collect and how you'd correlate it to identify root causes. Discuss alert design: what should trigger alerts? How do you avoid false positives? How would you set up monitoring to catch this type of problem in the future?
Practice Interview
Study Questions
Root cause analysis and systematic improvement
Distinguish between symptoms and root causes. Think about why the problem occurred at a fundamental level. Discuss systemic improvements to prevent recurrence. Explain how you'd design systems to be more robust against similar failures. Show that you think about long-term reliability improvement, not just firefighting.
Practice Interview
Study Questions
Network troubleshooting and connectivity diagnosis
Diagnose network problems: DNS failures, routing issues, connectivity problems, port conflicts, firewall blocks, and connection timeouts. Master tools: ping, traceroute, dig, nslookup, telnet, nc, netstat, ss, tcpdump. Understand TCP/IP basics, DNS resolution process, and common network failure modes in distributed systems.
Practice Interview
Study Questions
Production incident diagnosis and response
Master the incident response mindset and methodology: understand the timeline and scope, gather system data systematically, formulate hypotheses about root cause, test hypotheses methodically, identify the true root cause, propose and implement solutions. Practice diagnosing realistic scenarios: latency spikes, error rate increases, resource exhaustion, memory leaks, dependency failures, cascading failures. Discuss how you'd communicate during an incident and what information you'd track.
Practice Interview
Study Questions
Linux systems and performance diagnostics
Deep proficiency with Linux systems: process management, file systems, permissions, system calls, memory management, and CPU scheduling. Master diagnostic tools: top, ps, iostat, vmstat, netstat, ss, strace, tcpdump, and others. Understand how to identify resource bottlenecks (CPU, memory, disk I/O, network). Be able to interpret system behavior from monitoring data.
Practice Interview
Study Questions
Onsite Interview - Behavioral and Leadership
What to Expect
Behavioral and culture-fit interview assessing your values, collaboration style, leadership potential, and how you handle challenges. For a mid-level SRE, interviewers specifically evaluate: your ability to own projects end-to-end (not just execute tasks), mentoring and developing junior colleagues, collaboration across team boundaries, incident leadership and decision-making under pressure, learning from failures and continuous improvement, and alignment with Meta's engineering culture and values. You'll be asked about past experiences, decision-making processes, conflict resolution, and your philosophy on reliability.
Tips & Advice
Prepare 4-5 strong STAR-format stories (Situation-Task-Action-Result) demonstrating key mid-level competencies: (1) owning a project end-to-end, from conception to production, (2) mentoring or helping junior colleagues grow, (3) leading or significantly contributing to incident resolution, (4) driving process improvements or efficiency gains, (5) learning from failure and improving. At mid-level, emphasize ownership and impact—this differentiates you from junior level. Be specific with metrics when possible (e.g., reduced on-call load by 70%, mentored 3 junior engineers, improved deployment frequency from weekly to daily). Discuss your philosophy: how do you balance reliability and velocity? When do you invest in reliability vs. shipping features? Discuss your approach to on-call work and incident response culture. Show that you value learning, continuous improvement, and psychological safety for the team. Prepare thoughtful questions about the team's challenges, how SREs are valued, growth opportunities, and the incident response culture. Be authentic—share genuine challenges you've faced and what you learned. If asked about failures, discuss honestly what went wrong, what you learned, and how you improved. Meta values intellectual humility and honesty about challenges.
Focus Topics
Learning from failure and growth mindset
Discuss a significant failure, mistake, or setback you experienced. Be honest and vulnerable about what went wrong. Explain what you learned and how you improved as a result. Show that you view failures as learning opportunities, not sources of shame. Demonstrate resilience and commitment to continuous improvement.
Practice Interview
Study Questions
Cross-functional collaboration and influence without authority
Share examples of working effectively with product teams, infrastructure teams, and other stakeholders. Discuss how you advocate for reliability improvements and communicate about tradeoffs. Show your ability to influence others' decisions and build consensus around your ideas without having direct authority over them.
Practice Interview
Study Questions
Project ownership and end-to-end impact
Describe projects you've owned from conception through production and maintenance. Share what problems you identified, your approach to solving them, implementation challenges you overcame, and measurable impact (improved reliability, reduced toil, faster response time, etc.). Demonstrate your ability to drive initiatives independently, make decisions, and see projects through to completion. Show that you don't just execute tasks but own outcomes.
Practice Interview
Study Questions
Mentoring and developing junior team members
Share examples of how you've helped junior engineers or colleagues grow: code reviews, pairing sessions, teaching them new tools or concepts, guiding them through complex problems. Discuss your philosophy on mentoring. Show that you're invested in developing others and creating a learning culture. Describe the impact: how did they improve?
Practice Interview
Study Questions
Incident leadership and decision-making under pressure
Discuss your role in major incidents: did you lead incident response, contribute significantly to diagnosis, make critical decisions? Explain your approach: how do you stay calm under pressure? How do you communicate with stakeholders? What information drives your decisions? Discuss your philosophy on blameless post-mortems and learning from failures. Share examples of incidents where you drove resolution or subsequent improvements.
Practice Interview
Study Questions
Frequently Asked Site Reliability Engineer (SRE) Interview Questions
List and describe the common categories of problematic inputs an SRE should consider when testing a service (for example: null/empty, single-element, duplicates, negative/out-of-range, very large values, unusual encodings). For each category give one concrete example relevant to an HTTP API and one suggested automated test.
Sample Answer
Direct answer
A site reliability engineer (SRE) testing a service's input handling should think in categories, not individual bad values: null/empty, single-element/minimal, duplicate, negative/out-of-range, very large, and unusual-encoding inputs each stress a different layer of the system (parsing, storage, business logic, or resource limits), and a service that handles one category correctly can still fail every other one.
Structured elaboration
| Category | HTTP API example | Suggested automated test |
|---|---|---|
| Null / empty | POST /users with {"email": ""} or the field omitted entirely | Send the missing/empty variant; assert a 4xx validation error and confirm no record was created |
| Single-element / minimal | GET /items?limit=1 | Request the smallest allowed page size repeatedly; verify response shape and pagination metadata stay correct at the boundary |
| Duplicates | POST /orders sent twice with the same client-supplied idempotency key | Replay the identical request; assert the second call returns the same result as the first and only one order was created |
| Negative / out-of-range | PATCH /account with {"credit": -1000000} | Send a negative and an absurdly large value; assert rejection and confirm no partial state change occurred |
| Very large / oversized | POST /messages with a 100 MB body | Upload an oversized payload; assert a clean rejection (e.g. HTTP 413) with bounded memory use, not a timeout or crash |
| Boundary values | A username field at exactly its documented max length, and one character over | Submit both; assert the max-length value is accepted and the one-over value is rejected |
| Malformed / wrong type | POST /json sent with Content-Type: application/json but a form-encoded body | Send the mismatched payload; assert a 400 response and no side effects |
| Unusual encodings | PUT /profile with a name field containing an emoji or a Zero-Width Joiner (ZWJ) sequence | Send Unicode-heavy input; assert correct storage and retrieval, and no downstream rendering or injection issue |
| Slow / partial input | A client that sends headers, then stalls mid-body indefinitely (a "slowloris"-style connection) | Simulate a stalled or chunked-and-abandoned upload; assert connection timeouts and limits protect overall service health |
Worked example
For the negative/out-of-range category specifically: an account-balance endpoint accepting {"credit": -1000000} without a lower-bound check does not just return a wrong number, it can leave the account in a state the business logic elsewhere assumes is impossible (a negative credit balance that a downstream billing job was never written to handle), which is why the automated test for this category has to assert no partial state change occurred, not only that the HTTP response was an error code. A response-code-only test can pass while the write already happened underneath it, if validation runs after the write instead of before.
Trade-offs & pitfalls
The most common gap in an SRE's test coverage is treating "the service returned a 4xx" as sufficient evidence of correct handling, when the actual risk categories above (duplicates, malformed input, slow/partial input) are as much about resource and state protection as they are about the HTTP response code; a service can return the textbook-correct error code while still leaking a connection, partially writing state, or degrading shared capacity for other requests. Security-relevant categories deserve extra weight in prioritization, unusual encodings and malformed/wrong-type input are the categories most likely to be actual injection or parser-exploitation vectors rather than "merely" correctness bugs, so an SRE reviewing test coverage should check those categories are automated, not just manually spot-checked once. Production logging and monitoring is the practical way an SRE discovers categories a test suite missed entirely, a spike in a specific 4xx/5xx code, or an unexpected input shape appearing in error logs, is often the first signal that a real-world input pattern exists that the original test-case brainstorm never considered.
Leadership hands down an expectation you know is unrealistic (for example, 'zero incidents within six months', or a content decision your own analysis contradicts). Walk me through the counter-proposal you would prepare: how you set more realistic, measurable expectations, what trade-offs and investments you'd name, and how you'd deliver that pushback upward.
Sample Answer
When leadership hands down a target that isn't achievable without unacceptable trade-offs, don't argue against the goal itself. Accept the intent behind it, then come back with a written, staged counter-proposal that shows the current baseline, a realistic trajectory, and what it costs to move faster. When the ask is a specific decision you disagree with rather than a broad mandate, the same posture holds: bring your own counter-analysis, state it clearly once, and commit to executing whatever the leader ultimately decides, a pattern often called disagree-and-commit: you raise your objection once, then execute the decision as made even though you disagreed with it.
Two shapes of upward pushback
| Shape | What triggers it | What you bring | How you deliver it |
|---|---|---|---|
| Counter-proposal to a mandate | A broad, unrealistic target ("zero incidents in six months") | Baseline data, staged targets, named trade-offs and investment options | A written proposal, reviewed before any live meeting |
| Counter-analysis to a decision | A specific call you disagree with | Your own analysis of why the decision is risky, delivered once, not repeated | A direct, private conversation, followed by disagree-and-commit |
Building the counter-proposal
- Diagnose the real concern behind the mandate. "Zero incidents" is usually a proxy for something specific: a recent outage, a board commitment, a customer escalation, not a literal target anyone expects to hold forever.
- Anchor to a baseline. Pull the org's own current numbers before proposing anything, so the counter-proposal isn't a negotiating position, it's grounded in what's actually happening.
- Reframe into a staged, measurable target with a defined ceiling and a trajectory, plus checkpoints along the way rather than one deadline at the end.
- Name the trade-offs and investment as a menu, not a single ask, and state explicitly what happens if only part of it is funded (which milestone slips, not just "it'll be slower").
- Put it in writing before any live discussion. A written artifact can be reviewed, forwarded, and revised without forcing the leader to back down in front of others, which is why it lands better than live pushback.
Handling disagree-and-commit on a specific decision
- When leadership has already made a call you think is wrong, state your counter-analysis plainly, once, with evidence.
- Make sure the decision-maker has genuinely heard it, not just tolerated it.
- Then commit to executing the decision as made. Reserve further escalation for cases where the decision would cause real, material harm, not for cases where you simply preferred a different call.
Worked example
A reliability team lead is told, right after a bad outage, to get to "zero customer-visible incidents" within two quarters. Agreeing outright sets the team up to either burn out chasing an unreachable number or quietly ignore the mandate, both of which cost credibility later.
The lead pulls the last two quarters of incident data by severity and finds a clear downward trend with a small, largely low-severity floor that behaves like background noise rather than a fixable defect. Instead of debating "zero is impossible" in the room, the lead sends a short written proposal: reduce the highest-severity incidents to a defined ceiling by the end of each quarter, treat the remaining low-severity noise as an explicit accepted error budget (an agreed allowance for how much low-severity failure is tolerable before it counts against the target), and name the concrete investment needed (a restructured on-call rotation and dedicated time for automated rollback tooling). The proposal states plainly what happens with partial funding: the timeline to the ceiling slips by one quarter, named explicitly. It also includes a two-week checkpoint so leadership sees early movement well before the first quarter closes.
Leadership accepts the staged plan with checkpoints. "Zero incidents" quietly becomes "zero high-severity incidents by quarter end, with an explicit error budget on the rest," and the lead reports against that framing from then on.
What a senior person does differently here: separate the emotional ask (leadership wants confidence that this is being taken seriously) from the technical ask (a number), answer the emotional need with a reporting cadence and the technical need with a staged, evidence-backed target, and get it in writing so the agreement is durable rather than something that has to be re-argued later.
Trade-offs and pitfalls
- Pushing back live and unprepared reads as excuse-making, not a plan. Bring the written proposal first.
- Agreeing to the unrealistic number just to avoid conflict is worse than pushing back: failing publicly against a number you privately knew was wrong costs more credibility than the original pushback would have.
- Staged targets are more credible but slower to signal urgency, so pair them with a real, visible early move (not just a promise) to show the concern is being taken seriously now.
- Disagree-and-commit is not silent compliance and not endless re-litigating. State the counter-analysis once, clearly, then commit.
A dynamic array (Python list, Java ArrayList, C++ vector) doubles its backing capacity whenever it fills up. Explain why append is still considered O(1) on average even though an individual append can trigger an O(n) copy, and what would happen to that guarantee if the growth strategy added a fixed amount of capacity each time instead of doubling it.
Sample Answer
Direct answer
Append is O(1) amortized (amortized meaning the average cost per operation across a whole sequence of operations, not the cost of any single call) because the expensive O(n) resize-and-copy step happens rarely, and its cost can be spread over the many cheap O(1) appends that occur between resizes. Summed over any sequence of n appends, the total work stays proportional to n, so the average cost per append is a constant. That guarantee depends specifically on doubling (or any fixed multiplicative growth factor); if capacity instead grew by a fixed additive amount each time, resizes become frequent enough that total copying work grows like O(n2), which makes the amortized cost per append O(n) instead of O(1).
Structured elaboration
Proof sketch for doubling (α=2)
Start empty and perform n appends. Each append either writes into a free slot (cost 1) or triggers a resize that copies the current m elements before writing. Because capacity doubles, the sizes copied across all resizes form the series 1,2,4,8,… up to just under n:
1+2+4+⋯+2k<2n
So total cost across all n appends is at most n (the simple writes) plus 2n (the copying), giving:
amortized cost≤nn+2n=3=O(1)
For a general multiplicative factor α>1, the copied sizes form a geometric series bounded by α−1α⋅n, so the amortized constant is roughly 1+α−1α: about 3 for α=2, about 4 for α=1.5, and growing without bound as α→1+.
What breaks with fixed additive growth
If capacity instead grows by a fixed amount c each time (not multiplied), resizes happen roughly every c appends, and the k-th resize copies about kc existing elements. Summed over n/c resizes:
total copy cost=k=1∑n/ckc=c⋅2(n/c)(n/c+1)≈2cn2
Total work across n appends is now O(n2), so the amortized cost per append is O(n2)/n=O(n): linear per operation on average, not constant. Additive growth trades away the amortized guarantee entirely; it doesn't just make the constant worse, it changes the complexity class.
Reference point (not a claim about your specific runtime, just why factors below 2 are common): production dynamic-array implementations often deliberately avoid a factor-2 growth to reduce peak wasted memory, accepting a larger amortized constant in exchange (for example, growth factors noticeably below 2 are common in real-world implementations). The trade-off is always time (fewer resizes) versus space (less transient waste).
Worked example
Running the doubling and fixed-increment growth strategies and tracking total bytes copied per element appended (all inputs pinned, no timing claims, just operation counts):
def total_copy_cost_doubling(n: int) -> tuple[int, int]:
"""Simulates n appends into a dynamic array that doubles capacity
on overflow. Returns (total elements copied across all resizes,
number of resizes)."""
cap = 1
size = 0
total_copy = 0
resizes = 0
for _ in range(n):
if size == cap:
total_copy += cap # copy every existing element
cap *= 2
resizes += 1
size += 1
return total_copy, resizes
def total_copy_cost_additive(n: int, c: int) -> tuple[int, int]:
"""Same simulation, but capacity grows by a fixed amount c each
time instead of doubling."""
cap = 0
size = 0
total_copy = 0
resizes = 0
for _ in range(n):
if size == cap:
total_copy += cap
cap += c
resizes += 1
size += 1
return total_copy, resizes
if __name__ == "__main__":
print("doubling: n -> total_copy, copy/n")
for n in (1_000, 10_000, 100_000, 1_000_000):
total_copy, _ = total_copy_cost_doubling(n)
print(n, total_copy, round(total_copy / n, 3))
print("additive (c=8): n -> total_copy, copy/n")
for n in (1_000, 2_000, 4_000):
total_copy, _ = total_copy_cost_additive(n, c=8)
print(n, total_copy, round(total_copy / n, 3))
Running this prints:
doubling: n -> total_copy, copy/n
1000 1023 1.023
10000 16383 1.638
100000 131071 1.311
1000000 1048575 1.049
additive (c=8): n -> total_copy, copy/n
1000 62000 62.0
2000 249000 124.5
4000 998000 249.5
The doubling column stays in a narrow band (roughly 1 to 1.6) no matter how large n gets, which is the empirical signature of O(1) amortized cost. The additive column roughly doubles every time n doubles, which is the empirical signature of the amortized cost growing linearly with n, i.e., O(n) per append on average.
Trade-offs & pitfalls
- A larger growth factor means fewer resizes and a lower amortized constant, but more wasted memory sitting unused right after a resize (up to nearly half the array, for doubling).
- A growth factor close to 1 keeps memory tight but causes frequent resizes and a larger amortized constant; taken to the extreme (fixed additive growth), it loses the O(1) guarantee altogether.
- Amortized O(1) is a statement about the long-run average, not a promise that every individual call is fast: a single append can still legitimately cost O(n) when it happens to trigger the resize. That distinction matters in a hot loop with a strict per-call latency budget, where an occasional O(n) spike may be unacceptable even though the average is fine.
- Shrinking on removal needs the same care: if you shrink back to exactly the current size whenever the array isn't full, an alternating pattern of append-then-remove near that boundary can trigger a resize on almost every operation (grow/shrink thrashing). The standard fix is asymmetric thresholds, for example only shrinking once usage drops to a quarter of capacity, and halving (not shrinking all the way to fit) when it does.
In a long-lived system, how do you evolve a structured logging or metrics schema over time, for example adding a new field or changing what a field means, without breaking dashboards, alerts, and tooling that depend on the old schema?
Sample Answer
Direct answer
Default to additive-only changes (new optional fields with sane defaults), never silently repurpose an existing field's name or meaning, and when the meaning genuinely has to change, introduce it as a new versioned field and dual-emit both the old and new during a defined deprecation window so every consumer (dashboards, alerts, downstream jobs) has time to migrate before the old one disappears.
Structured elaboration
Additive changes are the default and the cheap case
Adding a brand-new field with a sensible default (or simply absent, if consumers already tolerate unknown fields) is safe: existing dashboards and alerts that don't reference it are unaffected, and new tooling can start using it immediately. Most schema evolution should fit this case; if it doesn't, that's a signal the change is more than "add a field."
Never repurpose a field in place
Changing what an existing field means (e.g., a latency field that used to be measured in milliseconds and is now measured in microseconds, keeping the same name) is the most dangerous kind of change, because it fails silently: old dashboards keep running the same query and now show numbers that are wrong by a constant factor, with no error to alert anyone. A rename or unit change should always get a new field name (latency_ms retired in favor of latency_us, both emitted for a transition period), never an in-place redefinition.
Version the schema explicitly
Tag every emitted record with a schema_version. Consumers that need to branch on shape (a downstream parser, a strict dashboard query) can check the version rather than guessing from field presence. This also gives you a clean place to document exactly which version introduced which change.
Deprecation as a process, not an event
- Announce the field's replacement and the planned sunset date.
- Dual-emit: write both the old and new field for a fixed window.
- Track actual usage of the old field (query logs, dashboard/alert definitions referencing it) to confirm consumers have migrated, not just assume they have.
- Only stop emitting the old field once usage has genuinely dropped to zero (or the sunset date passes and remaining consumers have been explicitly notified they'll break).
Testing the transition
Contract tests (automated checks that a producer's output still satisfies what a known consumer expects) and shadow validation (running the old and new emission side by side and diffing the derived metrics they produce) catch the case where the "safe" additive change turns out to interact badly with an existing aggregation, before it reaches production dashboards.
Worked example
A service currently emits {"latency": 245, ...} where latency is milliseconds, and the team wants to switch to microsecond precision.
Wrong approach (in-place redefinition): change the emitter to write {"latency": 245000, ...} under the same field name. A dashboard panel computing avg(latency) over the last hour now silently reports a number 1000x larger with zero errors or warnings; anyone glancing at the dashboard sees "avg latency: 245000ms" and either panics or, worse, doesn't notice because the panel has no sanity bound configured.
Correct approach: add latency_us alongside the existing latency field, dual-emit both for a stated transition window (e.g., until every dashboard query referencing latency has been rewritten to use latency_us, confirmed by grepping the dashboard/alert config repository for the old field name), then drop latency only after that grep returns zero references.
The key diagnostic in this example: the failure mode is not "the pipeline throws an error," it's "the pipeline keeps running and produces a wrong number that looks plausible." That's why additive-with-a-new-name is the default, not an optional extra step.
| Strategy | Backward compat risk | Consumer effort required | When to use |
|---|---|---|---|
| Additive field, new name | None | None (opt-in) | Default choice for any new signal or unit/meaning change |
| Field deprecation (dual-emit then drop) | Low, if the window is long enough and usage is tracked | Must update queries before sunset | Retiring a field that's being replaced |
| In-place semantic change (same name, new meaning) | High: silent, no error | None until someone notices wrong numbers | Avoid; only defensible for a field with zero known consumers |
Trade-offs & pitfalls
- Dual-emitting indefinitely accumulates cost and confusion; every deprecation needs an explicit sunset date, not an open-ended "eventually."
- Tracking actual field usage (rather than assuming consumers migrated because you announced it) is the step most teams skip, and it's exactly the step that prevents a surprise outage when the old field is finally dropped.
- Additive changes still need CI-enforced schema compatibility checks (backward/forward compatibility validation), because "just add a field" can still break a strict consumer that rejects unknown fields.
- A silent semantic change is strictly worse than a loud break: a query that errors gets noticed and fixed; a query that keeps returning a plausible-looking wrong number can go unnoticed for months.
Describe how to implement a canary deployment using only native Kubernetes primitives (no service mesh): creating and controlling the canary ReplicaSet, shifting traffic gradually, evaluating metrics, and automating promotion or rollback.
Sample Answer
Direct answer
Without a service mesh, a canary on native Kubernetes primitives means running a SEPARATE, smaller ReplicaSet for the canary version, sharing the same Service (and therefore the same label selector) as the stable ReplicaSet, and controlling the traffic split purely by the RATIO of canary-to-stable pod counts, since without a mesh there's no fine-grained percentage-based routing, only "however many pods exist, roughly that share of traffic."
Structured elaboration
- Two ReplicaSets, one Service: the stable Deployment/ReplicaSet and a separate canary ReplicaSet both carry a label the shared Service selects on (e.g.
app: checkout-api), so Kubernetes' built-in load-balancing (round-robin across matching endpoints) sends traffic to both, with the SPLIT determined by relative pod count, not an explicit percentage. - Shifting traffic gradually: scale the canary ReplicaSet up (and optionally scale stable down proportionally) in steps, for example canary at 1 of 100 total pods (~1%), then 5 of 100 (~5%), then 25, then fully replacing stable. This is coarser-grained than a mesh's weighted routing (you're limited by pod-count granularity, especially at low replica counts) but requires no additional infrastructure.
- Evaluating metrics: since both versions share one Service, you need the canary pods separately LABELED and QUERYABLE (a
version: canarylabel alongside the sharedapplabel) so your metrics system can filter and compare canary-specific metrics against stable, even though both are receiving traffic through the same Service. - Automating promotion/rollback: a script or controller that watches the canary-specific metrics, and on a pass, scales the canary ReplicaSet up (and stable down) to the next step; on a fail, scales canary back to zero and stable back to full, reverting via the same ReplicaSet-scaling mechanism.
Worked example
At 100 total desired pods: canary starts at 1 replica (stable at 99), giving roughly 1% of traffic via Kubernetes' round-robin balancing across matching endpoints. After a clean observation window, canary scales to 5 (stable to 95), then 25/75, then finally canary fully replaces stable (canary scales to 100, stable to 0, and the canary Deployment is effectively promoted to become the new "stable").
Trade-offs and pitfalls
The coarse granularity is the real limitation: at low total replica counts, you can't achieve a genuinely fine percentage (with 10 total pods, the smallest non-zero canary slice is 10%, not 1%), and Kubernetes' round-robin isn't a precise, deterministic percentage split the way a mesh's weighted routing is, it's a rough approximation based on endpoint count. This approach is a reasonable, infrastructure-light starting point for teams without a service mesh, but the imprecision and lack of built-in session affinity or fine-grained routing rules are exactly what a mesh (or a load-balancer with native weighted routing, like an ALB) is built to solve properly.
Implement the smooth weighted round-robin algorithm in Python. The selector should accept a list of backends where each backend is a tuple (id, weight). Provide a class with a next() method that returns a backend id on each call. Explain time and space complexity and how this algorithm reduces short-term imbalance compared to naive weighted round-robin.
Sample Answer
Approach: Use the classic "smooth weighted round-robin" (as used by NGINX). Each backend keeps a current weight that is incremented by its static weight on each selection; pick the backend with the highest current weight and subtract the total weight from its current. This spreads requests proportionally while smoothing bursts.
class SmoothWeightedRoundRobin:
def __init__(self, backends):
"""
backends: list of (id, weight) tuples. weight must be non-negative integer/float.
"""
if not backends:
raise ValueError("backends must be non-empty")
self.backends = []
self.total_weight = 0.0
for _id, w in backends:
if w < 0:
raise ValueError("weights must be non-negative")
self.backends.append({"id": _id, "weight": float(w), "current": 0.0})
self.total_weight += float(w)
if self.total_weight == 0:
raise ValueError("total weight must be > 0")
def next(self):
# Add each backend's static weight to its current, pick max current
best = None
for b in self.backends:
b["current"] += b["weight"]
if best is None or b["current"] > best["current"]:
best = b
# Decrease the chosen backend's current by total weight
best["current"] -= self.total_weight
return best["id"]
# Example:
# sw = SmoothWeightedRoundRobin([("A", 5), ("B", 1), ("C", 1)])
# for _ in range(7): print(sw.next())
Key points:
- Time complexity: O(n) per selection (one pass to update and find max).
- Space complexity: O(n) to store backend state.
- Why smoother than naive weighted RR: naive approaches (e.g., repeating entries proportionally) can cluster selections and cause bursts; smooth WRR incrementally balances "current" values so picks are interleaved proportional to weights, minimizing short-term imbalance and jitter.
- Edge cases: empty list, total weight zero, negative weights handled. For very large n or extreme throughput, consider a heap/tree to reduce selection to O(log n) at cost of more complex updates.
A postmortem is written, everyone nods along, and six months later a new team hits the same problem because nobody found the earlier write-up. How would you make incident learnings genuinely discoverable and get stakeholders to actually adopt postmortem-recommended changes, rather than leaving the findings as a static document nobody revisits?
Sample Answer
Direct answer
Converting postmortem findings into durable organizational knowledge means making them genuinely discoverable when someone needs them later, not just archived, and actively driving adoption of the recommended changes rather than assuming a written document alone will change anyone's behavior.
Structured elaboration
- Make it searchable, not just stored. Consistent tagging (by system, by failure category, by team) and a real search interface matter more than where the document technically lives; a postmortem nobody can find when facing a similar problem six months later has produced no lasting value regardless of how good the analysis was.
- Link forward, not just file away. Connect the postmortem to the runbooks, code, or design docs it should influence, so someone reading the runbook for a related system encounters the relevant lesson in context, rather than only finding it if they happen to search the postmortem archive specifically.
- Distribute, don't just publish. A regular digest of recent postmortems' key lessons (even a short one, shared org-wide or per relevant team) reaches people who wouldn't have gone looking, and repeated exposure is often what actually changes behavior, not a single document existing somewhere.
- Drive adoption of the recommended change actively, not passively. If a postmortem recommends a new practice (mandatory pre-deploy data tests, for example), treat rolling that recommendation out as its own project: identify a pilot team, demonstrate impact with real before-and-after data, and use that evidence to build the case for broader adoption, rather than assuming the recommendation alone will spread on its own merit.
- Periodically revisit and retire stale entries. Old postmortems referencing systems that no longer exist or practices that have since changed clutter the knowledge base and erode trust in search results; a light periodic review keeps the archive useful rather than just growing.
Worked example
A postmortem recommends mandatory pre-deploy data-validation tests after a bad data pipeline change silently corrupted downstream reports. Six months earlier, a similar (if less severe) incident had happened and been documented, but the postmortem sat unread and the recommendation was never adopted broadly. This time, instead of just filing the new postmortem, the team: tags it clearly under 'data pipeline' and 'validation gap,' links it directly from the data-pipeline team's onboarding docs and runbook, and pilots the recommended pre-deploy test requirement with one willing team first. After demonstrating the pilot caught two would-be incidents before they shipped, real evidence rather than a hypothetical, the team presents that data to engineering leadership and uses it to justify making the practice mandatory org-wide, with the earlier postmortem now cited as the founding case study in the org-wide rollout communication.
Trade-offs and pitfalls
The most common mistake is treating 'we wrote it down' as equivalent to 'we learned from it,' when in practice a document with no distribution, linking, or active adoption effort is functionally invisible to everyone except the person who wrote it. A second is over-investing in an elaborate knowledge-management system before addressing the more basic problem, which is usually that nobody is actively driving adoption of any given recommendation.
What items should a code-review checklist contain to enforce production-quality, defensive-programming standards across distributed teams? Draft a prioritized checklist of at least eight review items, and for each one explain why it directly impacts production reliability or operability.
Sample Answer
Direct answer
A code-review checklist for defensive, production-quality standards should be short enough that reviewers actually use it every time, and should focus on the handful of items that correlate most directly with real production incidents: error handling, observability, resource leaks, secrets management, idempotency, and input validation, each with a concrete one-line test a reviewer can actually apply while reading a diff.
Structured elaboration
1. Error handling. Does every external call (network, database, file system) have explicit failure handling, and is there no bare, silent catch-and-ignore? This matters because a swallowed exception is one of the most common root causes of "the system silently stopped working and nobody noticed for days".
2. Observability. Does this change add or preserve logging/metrics for its new failure paths, not just its happy path? A new code path with no visibility into whether it's failing in production is effectively unmonitored the moment it ships.
3. Resource leaks. Are file handles, database connections, and locks acquired in this diff guaranteed to be released even when an exception occurs (via try/finally, a context manager, or the language's equivalent)? This matters because a resource leak in an error path specifically (the path least likely to be exercised in normal testing) is a classic source of a slow production degradation that only appears under sustained load or over a long uptime.
4. Secrets management. Does this diff introduce any hardcoded credential, API key, or token, or log anything that could contain one? This is a fast, mechanical check (often automatable via a pre-commit secret scanner) but still worth a human's attention, since scanners miss secrets embedded in less obvious places like a debug log statement.
5. Idempotency. If this diff adds or touches an operation that could be retried (by a client, a queue redelivery, or an internal retry mechanism), is that operation actually safe to run more than once? This matters because a non-idempotent operation that silently becomes retriable somewhere in the call stack is a duplicate-side-effect bug waiting to happen, often not caught until production traffic patterns exercise the retry path that testing never did.
6+. Input validation and the remaining prioritized items. Does every externally-supplied input reaching this code get validated at a clear boundary, rather than trusted implicitly? Beyond these top items, a fuller checklist includes: test coverage for the new failure paths specifically (not just the happy path), whether any deprecated or discouraged pattern was introduced, and whether the change includes a rollback plan for anything touching a schema or a stateful migration.
Why these six, and why prioritized. Each is chosen because it maps directly to a common, real production-incident root cause, and they are ordered so a reviewer under time pressure who only gets through the first three still caught the highest-impact categories.
Worked example
A pull request adds a new endpoint that calls an internal payments service and writes a record to a local database. Applying the checklist: (1) error handling: the diff has a bare except: pass around the payments call, flagged; (2) observability: no log line exists for the payments-call failure path, flagged; (3) resource leaks: the database connection is correctly used inside a context manager, passes; (4) secrets: no hardcoded credentials found, passes; (5) idempotency: the endpoint is a POST that creates a payment record with no idempotency key, and the client-facing API documentation doesn't mention retry safety, flagged as a real production risk given payments-adjacent code specifically; (6) input validation: the request body is validated via a shared schema, passes. Three of six items are flagged, and the two most severe (the swallowed exception and the missing idempotency key on a payments-adjacent endpoint) block the merge, while the missing log line is a required fix but not necessarily a hard blocker if paired with a fast-follow commitment.
Trade-offs and pitfalls
A checklist with thirty items reliably gets skimmed rather than actually applied under normal review-time pressure; keeping it to the highest-impact handful, with a concrete one-line test for each, is what makes it something a reviewer genuinely runs through on every diff rather than something referenced once and then forgotten. The most common failure mode for a checklist like this is treating it as a one-time training exercise rather than something enforced consistently: without periodic reinforcement (referencing it explicitly in review comments, tracking how often flagged items actually get raised) it tends to fade from active use within a few months of being introduced.
Explain how to design an LRU (least-recently-used) cache that supports get and put in O(1) time. Which two data structures do you combine, and why does neither one alone (just a hash map, or just a doubly linked list) achieve O(1) for both operations?
Sample Answer
Direct answer: An LRU (least-recently-used) cache combines a hash map (for O(1) key lookup) with a doubly linked list (for O(1) reordering and eviction) - a hash map alone can't track recency order in O(1), and a linked list alone can't look up a key in O(1); the combination gives each structure the job it's good at.
Structured elaboration
- A hash map alone gives O(1)
get/putby key, but has no notion of "which key was used least recently" without an O(n) scan - you'd need to store and update timestamps, then scan all entries to find the minimum, which is O(n) per eviction. - A doubly linked list alone naturally tracks recency (move a node to the front on every access, evict from the back), but finding a node by KEY to move it requires an O(n) linear search through the list.
- Combined: the hash map stores
key -> nodepointers into the linked list.get(key): hash-map lookup finds the node in O(1), then the node is unlinked and relinked at the front of the list in O(1) (doubly-linked, so both neighbors are known without a search).put(key, value): same O(1) lookup-and-move if the key exists, or O(1) insertion at the front plus (if over capacity) O(1) removal of the tail node, whose key is then also removed from the hash map. - The critical design detail: the hash map's VALUE isn't the cached value directly - it's a pointer/reference to the linked-list NODE, so that once you've found the node via the hash map, you can splice it within the list in O(1) without any further lookup.
Worked example
Trace put(1,'a'), put(2,'b'), get(1), put(3,'c') on a capacity-2 cache:
put(1,'a'): list =[1](front=back=1), map ={1: node1}.put(2,'b'): list =[2,1](2 is now most-recent, at front), map ={1: node1, 2: node2}.get(1): hash lookup finds node1 in O(1); since node1 is not already at the front, unlink it and relink at front: list =[1,2]. Returns'a'.put(3,'c'): over capacity (2 items already), so first evict the tail (2, the least-recently-used): remove node2 from the list AND delete key2from the map. Then insert 3 at the front: list =[3,1], map ={1: node1, 3: node3}.
Key 2 was correctly evicted because it was least-recently used relative to the get(1) access that promoted 1 - both the eviction (tail removal) and the promotion (move-to-front) happen in O(1) because the linked list's structure means every splice only touches a constant number of neighboring pointers.
Trade-offs & pitfalls
- If you used a SINGLY linked list instead of doubly linked, moving an arbitrary node to the front would require knowing its predecessor to unlink it - which means an O(n) search, defeating the purpose. The "doubly" part is not incidental; it's what makes O(1) splicing possible.
- Many candidates correctly identify "hash map + linked list" but then can't explain WHY neither alone suffices - be ready to name the specific operation (find-by-key for the list, recency-tracking for the map) that the other structure covers.
- This same hash-map-plus-doubly-linked-list pattern generalizes to any "O(1) lookup plus O(1) reordering" requirement, not just LRU - it's worth recognizing as a reusable pattern (e.g. LFU (least-frequently-used) caches use a similar idea with an extra layer for frequency buckets).
Describe a small, lightweight experiment or pilot you designed and ran without being asked to validate an assumption or hypothesis before committing to a larger build. Include the hypothesis, how you scoped the experiment down, what you measured, what you learned, and how that learning changed the plan.
Sample Answer
Direct answer
Running a small, self-initiated pilot before committing real time or budget to a big build turns an unproven belief into a quick, cheap answer; it counts as initiative precisely because nobody has to authorize testing something this small.
Structured elaboration
State the hypothesis as something that could actually turn out false, not a foregone conclusion dressed up as a test. Scope the pilot to the smallest version that could still support or falsify it, a handful of cases, one customer, a short window, a rough manual version instead of a built one. Decide up front what you're measuring and what result counts as a pass versus a fail, before running it, so an ambiguous result isn't reinterpreted afterward to fit what you wanted. Run it fast and cheap on your own initiative rather than waiting for a formal go-ahead to test something this bounded. Let the result genuinely change the plan, proceed, adjust, or drop it, rather than running the pilot as a formality for a decision that was already made. The same shape applies to a lightweight technical proof-of-concept before a larger engineering investment, a single-customer pilot before a full rollout, or a short, time-boxed product experiment before committing a roadmap to a feature.
Worked example
A site reliability engineer suspected a proposed caching layer would meaningfully cut load from a slow, expensive downstream call, but building the full caching infrastructure was weeks of work. The hypothesis: caching just the handful of most-repeated queries would cut load without needing the general solution. They scoped it down to a rough, manual cache keyed on the five most frequent queries, deployed on a single low-traffic path over a few days, explicitly not the general system. They measured how often those cached responses were reused before going stale, versus how often the expensive call still had to run. The reuse rate was high enough on those five queries to justify the larger investment, so they proposed building the full caching layer next, now with evidence for where it would pay off first, rather than starting the bigger build from a hunch alone.
Trade-offs and pitfalls
Scoping the pilot so small it can't actually fail teaches you nothing and just delays the real decision. Not deciding the pass or fail bar up front invites reading whatever result you get as a win. Running the pilot under conditions that don't resemble the real ones, wrong traffic pattern, wrong customer segment, produces a result that doesn't transfer. And the most common trap: the pilot goes fine, but nobody circles back to make the actual go or no-go call, so it lingers as a permanent unofficial workaround.
Recommended Additional Resources
- LeetCode (focus on medium to hard problems, especially graph traversal, dynamic programming, and data structure design)
- Designing Data-Intensive Applications by Martin Kleppmann (essential for understanding distributed systems)
- The Site Reliability Engineering Workbook by Google (covers SRE fundamentals and practices)
- Systems Design Interview by Alex Xu and Shuyi Liao (practical system design patterns)
- TCP/IP Illustrated Vol. 1 by W. Richard Stevens (comprehensive networking reference)
- Understanding the Linux Kernel by Daniel P. Bovet and Marco Cesati (deep Linux knowledge)
- Levels.fyi (compensation, interview experiences, company insights)
- Blind (anonymous employee feedback and interview discussions)
- Meta Engineering Blog and Infrastructure posts (understand Meta's tech stack and challenges)
- Practice mock interviews on Pramp or Interviewing.io with experienced interviewers
- Linux man pages and documentation (master command-line tools)
- Incident postmortem templates and blameless culture resources
- Production Readiness Checklist (research and understand what operational readiness means)
Search Results
Google Site Reliability Engineer (SRE) Interview (questions, process ...
You should expect questions around networking concepts, such as connectivity checks, DNS resolution, port conflicts, and routing. Example Google ...
50 Site Reliability Engineer (SRE) Interview Questions 2025
Most asked Site Reliability Engineering (SRE) interview questions · Q1. Differentiate between DevOps and SRE. · Q2. Why do you want to do a job in ...
Site Reliability Engineering Interview Questions - MentorCruise
Study Mode · 1. How do you deal with on-call emergency issues · 2. Which programming languages are you most comfortable working with? · 3. What steps would you ...
Top 25 SRE Interview Questions and Answers for 2025 - YouTube
Want to crack your SRE (Site Reliability Engineer) interview fast? This video covers the most commonly asked SRE interview questions and ...
Meta Site Reliability Engineer Interview Questions - NodeFlair
Utilizing advanced AI, our tool generates tailored interview questions based on your industry, role, and experience. Practice and receive feedback on your ...
Site Reliability Engineer (SRE) Interview Preparation Guide - GitHub
A collection of questions to practice with for SRE interviews · SRE Interview Questions · Sysadmin Test Questions · Kubernetes job interview questions · DevOps ...
Meta (Facebook) Site Reliability Engineer Interview Questions
Review this list of Meta (Facebook) site reliability engineer interview questions and answers verified by hiring managers and candidates.
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
Browse Site Reliability Engineer (SRE) jobs
AI-enriched listings across hundreds of company career pages
Explore Jobs