Senior Cloud Engineer Interview Preparation Guide - DoorDash
DoorDash, as a major delivery platform with complex distributed infrastructure, typically follows a structured multi-round interview process for senior technical roles. For a Senior Cloud Engineer position, candidates can expect a combination of technical assessments, system design evaluations, behavioral interviews, and potentially infrastructure architecture deep-dives. The process aims to evaluate cloud architecture expertise, infrastructure automation capabilities, problem-solving for scale, and cultural fit with DoorDash's engineering practices.
Interview Rounds
Recruiter Screening
What to Expect
Initial conversation with a recruiter to assess basic fit, background, and expectations. This round typically covers your background in cloud engineering, motivation for the role, location/relocation preferences, and compensation expectations. The recruiter will also provide information about the role, team structure, and interview process timeline.
Tips & Advice
Be conversational and genuine. Clearly articulate your experience with cloud platforms and why you're interested in DoorDash specifically. Ask thoughtful questions about the team size, cloud platform preferences, and types of infrastructure challenges they're solving. Show enthusiasm for the scale of problems at a logistics company. Avoid discussing salary expectations unless the recruiter brings it up first.
Focus Topics
Motivation and Cultural Fit
Your reasons for applying, interest in DoorDash's mission, and how your values align with the company's engineering culture.
Practice Interview
Study Questions
Cloud Platform Experience Overview
High-level summary of your experience with AWS, Azure, and/or GCP platforms, number of years working with cloud infrastructure, and scope of projects you've managed.
Practice Interview
Study Questions
Infrastructure at Scale Experience
Brief discussion of your experience managing infrastructure for high-traffic systems, multi-region deployments, or complex distributed architectures.
Practice Interview
Study Questions
Technical Phone Screen 1 - Cloud Architecture Fundamentals
What to Expect
First technical assessment conducted via video call, focusing on cloud architecture principles and your hands-on experience with cloud services. The interviewer will likely present real-world infrastructure scenarios and ask you to propose solutions, discuss trade-offs, and explain your design decisions. You may be asked to discuss existing infrastructure you've designed or improved.
Tips & Advice
Think out loud and explain your reasoning clearly. For any architecture question, discuss multiple approaches before settling on your recommendation. Be specific about which cloud services you'd use and why. Discuss non-functional requirements (availability, latency, cost, scalability) explicitly. Be prepared to draw or describe architecture diagrams. If asked about infrastructure trade-offs, acknowledge the business context - for instance, how cost optimization might affect performance or vice versa. Ask clarifying questions about requirements before diving into solutions.
Focus Topics
Network Architecture and Security
Virtual networks, subnets, security groups, VPCs, VPNs, load balancing, CDNs, and foundational security concepts like network segmentation and least privilege access.
Practice Interview
Study Questions
Infrastructure as Code (IaC) and Automation
Experience with tools like Terraform, CloudFormation, or Azure Resource Manager for infrastructure provisioning. Understanding state management, modularity, and best practices for maintainable IaC.
Practice Interview
Study Questions
Multi-Region and High Availability Architecture
Design patterns for multi-region deployments, disaster recovery, failover mechanisms, data consistency across regions, and managing infrastructure across multiple cloud regions.
Practice Interview
Study Questions
Cloud Service Selection and Trade-offs
Ability to choose appropriate cloud services (compute, storage, networking, databases) for specific use cases, understanding when to use managed services vs. self-managed solutions, and trade-offs between cost, performance, and operational complexity.
Practice Interview
Study Questions
Technical Phone Screen 2 - Infrastructure Operations and Problem Solving
What to Expect
Second technical phone screen focusing on operational concerns, troubleshooting skills, and how you approach complex infrastructure problems. The interviewer will present scenarios involving performance issues, cost optimization, reliability challenges, or capacity planning. This round assesses your ability to diagnose issues, propose solutions, and think systematically about infrastructure problems.
Tips & Advice
For troubleshooting scenarios, use a systematic approach: start with understanding the symptoms, define the scope (affected services, blast radius), check monitoring and logs, form hypotheses, and test them. For optimization problems, discuss measurable impact and trade-offs. Share examples from your experience where you identified and resolved infrastructure issues. Be comfortable discussing monitoring strategies, alerting, and incident response processes. Demonstrate understanding of cost optimization levers (instance sizing, reserved capacity, commitment discounts).
Focus Topics
Performance Optimization and Scaling
Approaches to improving infrastructure performance, horizontal and vertical scaling strategies, caching layers, database optimization, and capacity planning for traffic growth.
Practice Interview
Study Questions
Monitoring, Logging, and Observability
Designing monitoring strategies, implementing meaningful alerts, log aggregation and analysis, distributed tracing, and metrics collection for infrastructure health assessment.
Practice Interview
Study Questions
Cost Optimization
Strategies for reducing cloud spend including instance right-sizing, reserved capacity planning, spot instances, data transfer optimization, and identifying waste. Understanding the business impact of infrastructure costs.
Practice Interview
Study Questions
Troubleshooting and Diagnostics
Systematic approach to diagnosing infrastructure issues including performance problems, connectivity issues, and reliability concerns. Understanding monitoring, logging, and observability tools.
Practice Interview
Study Questions
System Design Interview - Cloud Infrastructure Architecture
What to Expect
Deep-dive system design interview focusing on designing large-scale cloud infrastructure for a complex scenario, likely related to logistics, delivery, or distributed systems. You'll be expected to propose end-to-end infrastructure architecture, discuss component selection, capacity planning, failover strategies, and trade-offs. This round typically occurs on-site or via video and lasts 60-90 minutes. You may be asked to design infrastructure for a specific feature or service scaling to millions of users.
Tips & Advice
Start by asking clarifying questions about scale, geography, latency requirements, consistency requirements, and budget constraints. Propose architecture in layers: compute, storage, networking, and data. Discuss redundancy and failover at each layer. Consider DoorDash's specific needs: real-time order tracking, high availability, multi-region support, and cost efficiency. Draw detailed architecture diagrams showing components, data flow, and communication patterns. Be prepared to discuss how your architecture evolves with scale. Address operational concerns: how would you deploy this? Monitor it? Recover from failures? Discuss trade-offs explicitly - is your design optimized for cost, performance, or reliability?
Focus Topics
Capacity Planning and Elasticity
Forecasting infrastructure needs, designing auto-scaling policies, handling traffic spikes, and planning for growth while maintaining cost efficiency.
Practice Interview
Study Questions
Disaster Recovery and Business Continuity
Designing for failure: RTO/RPO targets, backup strategies, geographic redundancy, failover mechanisms, and recovery procedures to ensure business continuity.
Practice Interview
Study Questions
Database and Storage Architecture
Selecting and designing database solutions for different access patterns, distributed data management, replication strategies, backup and recovery, and managing multiple storage tiers.
Practice Interview
Study Questions
End-to-End Infrastructure Design at Scale
Designing complete infrastructure architecture for services supporting millions of requests, including compute resources, storage solutions, networking components, and CDN strategy.
Practice Interview
Study Questions
Behavioral Interview - Leadership and Ownership
What to Expect
Behavioral interview conducted on-site focusing on your track record of ownership, leadership, collaboration, and problem-solving. You'll be asked about specific situations you've handled, decisions you've made, conflicts you've resolved, and how you've grown as an engineer. For a senior role, interviewers assess your ability to lead projects, mentor others, influence decisions, and drive results in ambiguous situations.
Tips & Advice
Use the STAR method (Situation, Task, Action, Result) for all stories. Prepare 6-8 examples covering: major infrastructure project you led, incident you handled and learned from, time you influenced a technical decision, conflict you resolved, failure and what you learned, time you mentored someone, and a decision balancing technical vs. business needs. For each example, be specific about your role, decisions you made, and measurable impact. Focus on demonstrating ownership - how you took initiative and drove results. Discuss how you involve team members and consider different perspectives. Be authentic and reflect on what you've learned.
Focus Topics
Collaboration and Influence
Examples of working across teams, influencing decisions without authority, resolving technical disagreements, and building consensus on infrastructure approaches.
Practice Interview
Study Questions
Incident Management and Problem Solving
Stories about serious production incidents you've managed: how you approached diagnosis, actions you took, and lessons learned. Demonstrating systematic thinking under pressure.
Practice Interview
Study Questions
Technical Decision Making
Examples of critical technical decisions you've made: how you gathered information, considered alternatives, involved stakeholders, and communicated decisions. Balancing technical and business concerns.
Practice Interview
Study Questions
Ownership and Project Leadership
Examples of infrastructure projects or initiatives you've owned end-to-end, from conception through execution and operations. Demonstrating ability to drive large technical projects to completion.
Practice Interview
Study Questions
Deep-Dive Technical Interview - Distributed Systems and Reliability
What to Expect
Deep technical interview focusing on complex distributed systems concepts, reliability engineering, and operational best practices. Topics may include consensus algorithms, distributed tracing, chaos engineering, SLI/SLO/SLA frameworks, or specific advanced cloud patterns. This round assesses your depth of knowledge in infrastructure fundamentals and ability to handle complex technical challenges.
Tips & Advice
For this round, demonstrate depth in advanced topics. Be ready to discuss complex concepts like eventual consistency, CAP theorem, distributed consensus, and failure scenarios. If discussing specific tools (like service mesh, distributed tracing), show hands-on understanding. For reliability discussions, talk about SLIs/SLOs and how they guide infrastructure decisions. Be prepared for follow-up questions diving deeper into your answers. If you're not sure about something, acknowledge it and discuss what you would research or ask. Use this round to show continuous learning and intellectual curiosity about infrastructure challenges.
Focus Topics
Chaos Engineering and Resilience Testing
Approaches to proactively testing infrastructure resilience: chaos engineering principles, failure injection, game days, and lessons learned from resilience testing.
Practice Interview
Study Questions
Advanced Cloud Patterns and Technologies
Expertise in advanced cloud patterns: microservices architecture, serverless, containers and Kubernetes, service meshes, API gateways, and when to use each pattern.
Practice Interview
Study Questions
Reliability and SLI/SLO/SLA Frameworks
Designing for reliability using SLI, SLO, and SLA frameworks. Understanding error budgets, how to measure reliability, and using data to drive infrastructure decisions.
Practice Interview
Study Questions
Distributed Systems Concepts
Understanding of fundamental distributed systems challenges: consistency models, CAP theorem, consensus algorithms, eventual consistency, and trade-offs in distributed architectures.
Practice Interview
Study Questions
Final Interview - Engineering Culture and Team Fit
What to Expect
Final round typically with a senior engineer or engineering manager, assessing overall fit with the team and organization. This round aims to understand your work style, how you approach collaboration, your growth mindset, and alignment with DoorDash's engineering culture and values. You'll likely discuss your career trajectory, what you're looking for in this role, and long-term career goals.
Tips & Advice
Be genuine and thoughtful in your responses. Ask meaningful questions about the team, engineering culture, growth opportunities, and infrastructure challenges ahead. Listen carefully to the interviewer's descriptions of the team and role. Share what appeals to you about DoorDash and this specific role. Discuss your growth as an engineer and what you want to focus on in this role. Be honest about your strengths and areas you want to develop. Ask about what success looks like in the first 90 days and what challenges the team is currently facing. Show genuine interest in being a good team member and contributing to the team's success.
Focus Topics
DoorDash Mission Alignment and Role Expectations
Your understanding of DoorDash's business, what excites you about the role, and how your goals align with what the team is working on.
Practice Interview
Study Questions
Career Growth and Learning Mindset
Your approach to continuous learning, examples of skills you've developed, what you want to learn in the next role, and how you stay current with cloud and infrastructure trends.
Practice Interview
Study Questions
Team Collaboration and Work Style
Your approach to working with teams, communication style, how you handle disagreements, and what kind of team environment you thrive in.
Practice Interview
Study Questions
Frequently Asked Cloud Engineer Interview Questions
Tell me about a time you had to trade off a cost optimization against feature velocity or another priority. What criteria did you use to decide, who did you involve, and how did you quantify the trade-off in a way that let you defend the decision afterward?
Sample Answer
Direct answer
The criteria that matter are the same whether the trigger is a client asking for a feature, a cost overrun you stumbled onto mid-quarter, or a proposal to cut capacity: put a dollar figure on both sides of the trade (the cost delta and the expected business value or risk avoided), find whoever actually owns the budget being spent and get them in the room instead of just your manager or the requester, and write the reasoning down so the decision can be defended later if someone questions it. The story below is a concrete instance of that pattern.
Structured elaboration
A senior answer to this question is really describing a repeatable decision process, not a one-off negotiation:
- Quantify both sides in the same unit. Convert the cost delta and the expected upside (revenue, retention, an SLA (service-level agreement) risk avoided, a deadline hit) into dollars wherever possible, even roughly. A trade-off argued as "fast but expensive" versus "slow but cheap" is unresolvable; one argued as "$18k/month for a projected $25k/month in incremental revenue" has a payback period you can debate.
- Time-box the decision and note reversibility. Is this a one-way door (a schema change, a customer commitment) or something you can walk back next sprint? Reversible decisions can be made faster and revisited; irreversible ones deserve the full stakeholder loop up front.
- Find the actual budget owner, not just the requester. The person asking for the feature (a product manager, a client-facing lead) usually isn't the person whose budget absorbs the cost. Pulling in finance or whoever owns the line item is what makes the eventual decision defensible instead of just "the loudest voice won."
- Write a short decision memo. State the options considered, the numbers behind each, and which one was chosen and why. This is the artifact you point back to later, whether that's a performance review, a postmortem, or someone in leadership asking "why did we spend $8k more that month."
- Instrument the outcome. Put monitoring or a review checkpoint on the decision so you find out if the assumptions were wrong, rather than discovering it a quarter later.
This holds across the variants interviewers tend to ask: a client-facing escalation just changes who's applying pressure and adds a contractual angle to weigh; discovering an overrun after the fact means you're doing steps 1 and 4 retroactively to decide whether to unwind it; a proposal to remove capacity to save money is the same trade-off with the sign flipped, the "feature" being protected is reliability or headroom rather than a new capability.
Worked example
Situation: A product team wanted three new real-time widgets added to a premium analytics dashboard to boost activation. Enabling them at current infrastructure would add roughly $18k/month in compute cost and about three weeks of engineering work.
Task: As the engineer who owned the dashboard backend, I needed to decide between shipping full real-time functionality on schedule or proposing a cost-constrained alternative, and to make that call in a way I could defend afterward.
Action: I built a short memo comparing two options: (A) full real-time rollout, three weeks, +$18k/month ongoing; (B) staggered rollout, ship one real-time widget immediately and batch the other two, same three-week timeline but only +$8k/month initially, with an additional week of follow-up work to add batching that would bring the run-rate down further. I estimated the upside using an existing A/B prototype: full rollout was projected to lift premium activation and retention enough to be worth roughly $25k/month, which made option A defensible on paper, but the team wanted more cost certainty before committing to that run-rate permanently. I brought the memo to the product manager, finance, and our DevOps lead, and we discussed the payback period and the operational risk of running three real-time streams at once.
Result: We chose option B. The team shipped on schedule with a smaller initial cost increase, then implemented batching the following sprint to bring the ongoing cost down further. I added per-widget cost tags and a cost dashboard so finance could see the run-rate without asking, plus an alert if spend moved meaningfully above the agreed baseline, so the next version of this conversation would start from data instead of memory.
Trade-offs and pitfalls
- Conceding without quantifying feels collaborative but sets a bad precedent. If you agree to absorb a cost increase without writing down the number and the reasoning, the next request has no reference point and the team relitigates from zero every time.
- Optimizing for cost alone ships a worse product than necessary. The point of quantifying both sides is to find the cheapest option that still delivers most of the value, not to default to the cheapest option period.
- Skipping the actual budget owner is the most common mistake. A decision made only between engineering and the requesting product manager can get overturned later when someone with financial authority sees the bill and wasn't consulted.
- Treating each trade-off as a one-time negotiation instead of setting a threshold or policy means the same conversation repeats every time a similar request comes in, instead of the team having a standing rule (for example, a cost-increase approval threshold) to fall back on.
Explain backpressure and throttling techniques you can use to protect services under overload. Compare client-side rate limiting, server-side throttling with HTTP 429, bounded queueing, and graceful degradation (shedding load). For synchronous APIs vs asynchronous processing, which techniques are preferable and why?
Sample Answer
Definitions
Backpressure is a downstream system signaling upstream, explicitly or implicitly, to slow down because it can't keep up. Throttling is proactively capping the rate of requests a system will accept, regardless of whether downstream has said anything. They're related tools for the same problem: protecting a service from being overwhelmed.
Comparing the four techniques
Client-side rate limiting. The client enforces its own cap (e.g., a token bucket that only allows so many requests per second). Cheap and simple, but only works if the client cooperates; it does nothing against a misbehaving or malicious client, so it's a courtesy mechanism, not a real defense.
Server-side throttling with HTTP 429. The server enforces a rate limit (commonly a token bucket or a leaky bucket (which drains requests at a fixed, steady rate, so anything beyond that overflows) per API key or IP) and rejects excess requests immediately with a 429 status and a Retry-After header. This protects the server unconditionally, the client can't opt out, but it only works well if clients actually implement backoff on 429; a client that retries immediately in a loop just keeps hammering the server.
Bounded queueing. Instead of rejecting immediately, admit requests into a fixed-size queue and process them in order. This smooths short bursts (a spike gets absorbed instead of instantly rejected) but the queue MUST be bounded: an unbounded queue under sustained overload grows without limit, and by Little's Law, growing queue length means growing wait time for everyone in it, plus real risk of running out of memory.
Graceful degradation (load shedding). Under overload, deliberately drop or downgrade lower-priority work first, serve a cached/stale response, skip an optional personalization step, to protect the core functionality for everyone else. This requires classifying requests by priority ahead of time; you can't shed intelligently if everything looks the same to the system.
Worked example: why an unbounded queue fails
L=λWwhere λ is the arrival rate, W is the average time a request spends in the system, and L is the average number of requests in the system at once.
normal: λoverload: λgap​=200 req/s, W=50ms⇒L=10 requests typically in flight (healthy)=500 req/s, downstream capacity=200 req/s=300 req/s, piling up in the queue every second, indefinitely⇒W (and therefore L) grows without bound until something breaks​The intuition: a queue can smooth a burst, but it cannot absorb a sustained rate that exceeds your processing capacity, it can only delay the point at which that becomes visible, while making it worse when it does.
Synchronous APIs vs. asynchronous processing
Synchronous, user-facing APIs: a client is actively waiting on the connection. A deep queue here just converts "fast error" into "slow success or eventual error", bad for perceived latency either way. Prefer a small bounded queue plus fast 429 rejection when it's full, combined with graceful degradation (serve a cheaper/cached response) rather than making the user wait behind a long line.
Asynchronous processing (queue consumers, background jobs): nobody is blocked in real time, so a deeper bounded queue plus consumer-side rate limiting is not just acceptable, it's the natural fit; workers catch up when capacity returns, and genuine failures go to a dead-letter queue (a separate holding queue for messages that repeatedly fail to process, so they aren't silently lost) rather than being shed. Backpressure here can also propagate upstream cleanly (the producer slows down when the queue nears its bound) without a user ever noticing.
Ransomware has encrypted parts of production, and you're not yet sure whether your backups are clean. Walk through how your continuity plan plays out here: who makes the call to formally declare this a business continuity event, what you communicate to stakeholders while the extent of the damage is still unknown, and how you decide the recovery sequencing (restore vs. rebuild vs. wait for forensics to clear).
Sample Answer
Direct answer
Ransomware forces continuity decisions before anyone has full information, so the plan has to give explicit authority to declare and communicate under uncertainty rather than waiting for forensics to finish. Declaration happens as soon as the trigger conditions are met, not once damage is fully understood; early communication says clearly what's known, what isn't, and when the next update comes, without speculating on cause or scope; and recovery sequencing is decided service by service against the criticality tiers, weighing restore speed against the real risk of reintroducing a still-compromised backup.
Who declares, and when
This follows the same declaration-authority structure as any other event: a named succession with pre-defined trigger conditions. Declaring is a formal, logged governance act, distinct from an engineer opening a SEV1 page: paging on-call gets people looking at the problem, while declaring activates the continuity plan itself, mobilizing the response team, authorizing emergency spend, and starting the plan's communication sequencing. The wrinkle specific to ransomware is that the trigger condition can't require knowing the full scope first, because that knowledge can take days. A workable trigger is "any Tier 1 or Tier 2 service confirmed encrypted or inaccessible due to suspected malicious activity," declared immediately and explicitly scoped as provisional, pending forensic confirmation, rather than held back until certainty arrives.
Communicating under genuine uncertainty
The discipline is separating what's confirmed from what's suspected, and saying so explicitly rather than overstating confidence or going silent until everything is known.
- Internally: which systems are confirmed affected, what's under investigation, and an honest ETA for the next update, not a resolution time nobody can promise.
- Externally and to regulators or legal, where applicable: factual, reviewed statements limited to what's actually known, because a premature claim about scope or root cause can create exposure that outlives the incident itself.
This is a communications-cadence problem before it's a technical one; it uses the same discipline as any crisis communication plan, just under a harder information constraint.
Recovery sequencing: restore, rebuild, or wait
This is a decision made per service, not once for the whole estate, driven by three inputs: the service's criticality tier (how much delay is tolerable), whether a backup for that service can be verified clean before it goes back into production, and whether forensics needs the current state preserved before anything is touched.
- Tier 1 services with a verified-clean backup restore first.
- Anything where backup integrity can't yet be confirmed waits, even if that extends the outage on an important service, because reintroducing compromised data or a re-infection vector turns one event into a second one.
- Rebuilding from a known-good baseline, rather than restoring a possibly-tainted image, is the fallback where clean-backup confidence can't be established in an acceptable window.
This sequencing decision belongs to the same governance structure that owns declaration and tiering, not to whichever team finishes their piece first, because it's a risk trade-off between speed and re-infection, not a technical task order.
Safeguards that need to already exist
None of the sequencing decision above is possible unless backups have integrity that ransomware itself can't reach. In practice that means an offline or logically isolated (air-gapped) copy that an attacker with production access can't also encrypt or delete, immutability or write-once retention on at least one recent backup generation so it can't be silently altered, and a routine of actually testing restores, not just confirming a backup job completed, so "verified clean" is a real, exercised capability during the event rather than a hope. Without these in place beforehand, the restore-versus-rebuild-versus-wait decision collapses to "wait," because there's no way to trust any backup's integrity.
Worked example
A mid-size logistics company detects encrypted files on its warehouse-management and billing systems overnight. The on-call commander declares a provisional continuity event within the hour, under the "confirmed encryption of a Tier 1 service" trigger, without waiting to know if data was exfiltrated. Internal communication at hour one reads: "Warehouse-management and billing confirmed encrypted; scope of other systems still under investigation; next update in 2 hours." Because the backup program maintains an air-gapped nightly copy that predates the infection and its integrity has been tested in prior quarterly exercises, billing (Tier 1, clean backup available) is prioritized for restore first. Warehouse-management's most recent backup can't yet be confirmed clean, so that system is rebuilt from a hardened baseline image instead of restored, extending its outage but avoiding the risk of reintroducing the compromise, a trade-off the commander makes explicitly and logs, rather than leaving it to whichever team is ready first.
Trade-offs and pitfalls
- Waiting for full forensic certainty before declaring or communicating anything feels safer but usually makes things worse: silence gets filled with speculation internally and, if it leaks, externally.
- Restoring quickly from an unverified backup to hit a recovery-time target can cause a second, worse event than the original outage. Speed has to be weighed against verified integrity, not assumed.
- Treating "wait for forensics" as the default for every system ignores the tiering work entirely; some services genuinely can't wait, which is exactly why the criticality tiers exist, to force that trade-off deliberately rather than applying one rule everywhere.
- Backup safeguards, air-gapping, immutability, tested restores, are cheap relative to discovering during a live event that every backup is also encrypted. This is a case where the pre-event investment directly determines whether the sequencing decision has good options at all.
Write a Terraform (HCL) snippet that creates an AWS CloudWatch alarm for a custom metric 'api_error_rate' which triggers when error rate exceeds 0.5% for 5 consecutive minutes, plus an SNS topic 'slo-breach-alerts' to notify subscribers. Include the required resource blocks and mention any IAM assumptions needed for CloudWatch to publish to SNS.
Sample Answer
Turning an SLO-breach signal into infrastructure means wiring a CloudWatch alarm on the metric your application already emits to an SNS topic that fans out to whoever needs to act.
Structured elaboration
The alarm needs a comparison operator, an evaluation period count, and a period length that together express "exceeds 0.5% for 5 consecutive minutes" (5 evaluation periods of 60 seconds each, all breaching); treat_missing_data needs an explicit choice (here, notBreaching, so a gap in metric publication does not itself trigger a false alarm, though a stricter policy might prefer breaching for a safety-critical metric, trading false alarms for never missing a real gap). The SNS topic is a separate resource so the alarm and its notification fan-out can be composed independently (e.g., reusing the same topic across several alarms).
Worked example (validated with terraform validate against a real Terraform install, AWS provider ~> 5.0)
resource "aws_sns_topic" "slo_breach_alerts" {
name = "slo-breach-alerts"
}
resource "aws_cloudwatch_metric_alarm" "api_error_rate_high" {
alarm_name = "api-error-rate-high"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 5
metric_name = "api_error_rate"
namespace = "Custom/API"
period = 60
statistic = "Average"
threshold = 0.5
alarm_description = "Fires when api_error_rate exceeds 0.5% for 5 consecutive 1-minute periods"
treat_missing_data = "notBreaching"
alarm_actions = [aws_sns_topic.slo_breach_alerts.arn]
}
This configuration passed terraform init and terraform validate cleanly (correct resource schema for both aws_cloudwatch_metric_alarm and aws_sns_topic, and a correctly-formed reference from the alarm's alarm_actions to the topic's ARN).
Trade-offs and pitfalls
The IAM side is easy to forget: CloudWatch needs no special role to publish to SNS when the alarm references the topic directly via alarm_actions (this is a managed, AWS-internal integration), but any SUBSCRIBER of the topic (a Lambda, an HTTP endpoint, a chat-ops integration) needs its own permission to receive from SNS, and that subscription is a separate resource entirely. A custom metric like api_error_rate must actually be published by the application (via the CloudWatch PutMetricData API or an agent); this Terraform only wires the ALARM, not the metric's ingestion, so verify the metric is actually flowing before trusting the alarm.
A customer requires that S3 buckets only be accessed from within their VPC via VPC Gateway Endpoints (no public internet access). Explain how you would configure the VPC endpoint and S3 bucket policies to enforce this, describe pitfalls such as cross-account access and console access, and state how you would verify enforcement. Provide policy-level guidance (no code required).
Sample Answer
Direct answer
Enforcing "S3 only from inside our VPC, never the public internet" is a two-sided control: a Gateway Endpoint routes the VPC's S3 traffic privately, and an S3 bucket policy with an explicit deny condition makes that the only way in, regardless of what any individual identity's permissions would otherwise allow. Neither side alone is sufficient: the endpoint alone just gives you a private path that requests can still bypass by going out over the internet with valid credentials, and the bucket policy alone has nothing to point at without the endpoint existing first.
Structured elaboration
Step 1: create the Gateway Endpoint and associate it with the private subnets' route tables. Once associated, requests to S3's published address ranges from resources in those subnets route through the endpoint rather than a NAT gateway (the device that swaps a private IP address for a public one to reach the internet) or the internet gateway.
Step 2: enforce it with a bucket policy condition, not just the endpoint's existence. The endpoint being present does not stop someone with valid AWS credentials and network access to the public internet from calling S3 from outside the VPC entirely (their laptop, a different account's compute, the AWS Command Line Interface (CLI) from home). The enforcement has to live on the bucket itself: an explicit Deny statement in the bucket policy that denies all S3 actions unless the request's aws:sourceVpce condition key matches your specific endpoint ID (or aws:sourceVpc if you want to allow any endpoint within a given VPC, not just one specific endpoint). An explicit deny in a bucket policy overrides any Allow granted elsewhere, including a user's own broad S3 permissions, which is exactly the property you need: no identity-based permission, however permissive, can route around this specific bucket's requirement.
Pitfall: cross-account access. If another AWS account legitimately needs access to this bucket (a common real case, not just an edge case to guard against), their requests will originate from their own VPC's endpoint, with a different endpoint ID and potentially a different VPC ID than yours. A condition scoped only to your specific aws:sourceVpce will silently break that legitimate cross-account access rather than erroring clearly, so the policy needs to explicitly enumerate every endpoint ID (or VPC ID) that is allowed to be the source, across every account that has a real need, and that list has to be kept current as accounts and endpoints change.
Pitfall: console access. The AWS Management Console itself does not originate S3 requests from inside your VPC. An administrator trying to browse the bucket's contents through the console UI is making the request from AWS's console infrastructure, not from an endpoint inside your VPC, so a policy that strictly requires aws:sourceVpce will also block console-based access to that bucket for everyone, including legitimate administrators, which is often the first thing that breaks and gets reported as "the policy doesn't work." If console access needs to remain possible, the policy has to carve out an explicit exception (for example, allowing a specific administrative role regardless of source, ideally still gated by other conditions like requiring multi-factor authentication) rather than trying to force all access through the VPC endpoint uniformly.
Verifying enforcement. Do not treat "the policy was written" as "the control works." Verify from at least three angles: (1) from inside the VPC, through the endpoint, confirm access still succeeds; (2) from outside the VPC entirely, using valid credentials that would otherwise have permission (a request from a personal machine, or from a different VPC without the endpoint condition satisfied), confirm access is now denied, and confirm the denial reason in the request's logs actually cites the condition, not some unrelated permission gap that would have denied it anyway; (3) review the account's access logs or the cloud provider's equivalent (for example, enabling S3 server access logging or the account-wide API activity log) specifically filtered to this bucket, looking for any successful request whose source does not match an expected endpoint, since a successful non-endpoint request is direct evidence the control has a gap somewhere.
Worked example
A healthcare analytics company stores de-identified patient datasets in an S3 bucket that must never be reachable except from the VPC running its analytics pipeline. The bucket policy denies all actions on the bucket and its objects unless the request's aws:sourceVpce matches the analytics VPC's specific S3 gateway endpoint ID, with one explicit exception: a narrowly scoped compliance-audit role, gated additionally by a requirement for multi-factor authentication, is allowed regardless of source, so an auditor can still review the bucket's configuration and access logs through the console without punching a hole in the control for everyone else. A second account belonging to a partner organization that legitimately needs read access to a specific prefix in the bucket is granted access through a second, explicitly listed endpoint condition referencing that partner account's own VPC endpoint, rather than being blocked outright or, worse, "solved" by weakening the policy to allow any source. Verification runs as a scheduled check: a script from outside the VPC attempts a read and confirms it is denied, a script from inside the VPC confirms it succeeds, and the bucket's access logs are reviewed weekly for any successful request whose source VPC endpoint is not on the explicitly approved list.
Trade-offs and pitfalls
The most common mistake is writing the deny condition, confirming that access from inside the VPC still works, and stopping there, without ever testing that access from outside the VPC is actually denied; a typo in the condition key or a policy Allow statement elsewhere in the account that unintentionally overrides the intended restriction (extremely rare for an explicit Deny, but a real risk if the policy is structured incorrectly) can leave the control silently ineffective while looking correct on the happy path. A second pitfall is treating this as a one-time setup: every new legitimate cross-account consumer, every new administrative tool that needs console-based access, and every account boundary change (an account merger, a new environment) needs the policy revisited, or legitimate access breaks in a way that gets "fixed" by loosening the condition rather than by adding the new source explicitly. Finally, remember what this control does and does not cover: it restricts the network path by which S3 can be reached, it does not replace identity-based least privilege; a compromised, over-permissioned role reachable from inside the approved VPC can still do damage to the bucket the policy does not prevent, since it satisfies the source condition legitimately.
Describe how you would perform capacity planning for a service projected to double its traffic in the next 6 months. Include how you'd calculate headroom, what scaling strategy you'd pick, what workloads you'd benchmark to validate your numbers, and how you'd weigh cost against performance.
Sample Answer
What I'd want to know first
Before I put a number on anything, I'd pull four things: the traffic profile (is it steady, bursty, or spiky through the day), the read/write mix (reads and writes scale very differently), the resource cost per request (how much CPU, memory, and database load one typical request consumes), and the existing SLA (service level agreement) or error budget (how much latency and error headroom I'm actually allowed to spend). Skipping this step and jumping straight to "just double everything" is the most common mistake, because growth is rarely uniform across every resource.
Headroom calculation
Say the service peaks at 3,000 requests per second (RPS) today, running on 20 instances. Load testing shows each instance holds a safe ceiling of about 175 RPS before p99 latency (the 99th percentile response time, the slowest 1 in 100 requests) starts climbing. That puts the fleet's tested ceiling at 20 x 175 = 3,500 RPS, so today's headroom is about 500 RPS, roughly 14% of the tested ceiling (500 of 3,500 RPS still unused).
If traffic doubles in 6 months, peak becomes 6,000 RPS. I'd size for that peak plus a buffer for forecast error, say 20%, giving a target ceiling of 7,200 RPS. At 175 RPS per instance that's 7,200 / 175 = about 42 instances, roughly doubling the fleet plus a bit more because the buffer also grows.
Scaling strategy
For a stateless web tier fronting a database, horizontal scaling (adding more instances of the same size) is usually the right default: no single-instance ceiling to hit, and it's cheaper to add commodity capacity than to keep buying bigger boxes. But I'd check the database write path separately, since it often becomes the actual constraint before the web tier does. If the database is the binding resource, the plan has to include read replicas, connection pooling limits, or a write-path change, not just more web servers.
What I'd benchmark
- A steady-state load test at the projected 6,000 RPS peak with the real production read/write mix, not a synthetic uniform load.
- A soak test (sustained load over hours) to catch memory leaks and connection pool exhaustion that only show up over time.
- A burst test that ramps quickly to the new ceiling, since sustained-load tests can hide how the system behaves under a sudden spike.
Cost versus performance
If each instance costs roughly $140/month, the fleet grows from $2,800/month to about $5,880/month, a cost increase of around 110% to support a 100% traffic increase, which is close to linear and reasonable. If the math came out sharply super-linear (say 300% cost for 100% traffic), that would push me to look at right-sizing the instance type or fixing an inefficiency instead of just buying more of the same box.
You have to choose between deepening technical skill in something that won't be visible for months, and shipping something with lower depth but higher visibility toward your next promotion. How do you decide, in the moment, which one to prioritize?
Sample Answer
Direct answer
Decide by diagnosing which constraint is actually binding right now: if it's a visibility or credibility gap, take the shippable path since it buys proof and goodwill; if it's a capability gap that will bottleneck everything after, invest the depth even though it won't show for a while. When genuinely unsure, default toward shipping, since visible momentum is what buys you the room to go deep later.
Structured elaboration
- Diagnose the binding constraint first. Ask directly: do people doubt I can do the harder thing (a visibility problem, solved by shipping), or can I genuinely not yet do it reliably (a capability problem, solved by depth)?
- Weigh the time horizon of the payoff. Depth work compounds, the skill gets reused across many future situations; shipping is mostly a point-in-time signal. The earlier you are in a role or level, the more depth tends to be worth relative to a single visible win.
- Look for a hybrid slice. Can part of the deep work be carved into something small enough to ship and visible enough to protect the time for the rest? This is often available and often missed.
- The same logic applies over a longer horizon. A lateral move offering real ownership but far less visibility is this same trade-off stretched over months instead of a single decision: the test is whether that ownership will eventually surface as something demonstrable, or whether it's ownership of something structurally invisible with no path to ever becoming visible.
Worked example
I was mid-way through work on a system that badly needed a deeper rewrite, work that wouldn't show results for a couple of months, right when a lower-effort, more visible feature request landed that would help my case going into a review cycle. I asked which was actually the binding constraint: I already had credibility for shipping, what I was missing was proof I could handle harder technical problems, so instead of choosing one or the other outright, I carved out the piece of the deep rewrite causing the most visible pain, framed it publicly as phase one of the larger effort, and used the resulting goodwill to protect time for the rest. The same question came up later at a larger scale, when I considered a lateral move into a role with far more ownership but almost no visibility; I only took it once I'd confirmed the ownership would eventually surface as something demonstrable, rather than staying invisible indefinitely.
Trade-offs & pitfalls
- Always choosing visibility produces a track record that looks credible but is shallow exactly when the next level starts expecting real depth.
- Always choosing depth risks being read as someone who goes quiet and doesn't ship, even when the eventual work is excellent.
- A hybrid slice isn't always available, and pretending there's always a clever middle path is itself a tell that you're avoiding an honest either/or call.
- For the lateral-move version specifically, the trap is accepting invisible ownership indefinitely on the promise it will "pay off eventually," with no concrete idea of how or when it becomes visible.
You're asked to estimate the effort, timeline, and resources needed for a bounded piece of technical work you'll own: for example, automating a regression suite, standing up cross-team logging and monitoring, building a service, or delivering a model. Walk through how you'd size it: your assumptions, the risk factors that could blow up the estimate, how you'd break the work into stages, and how you'd present the timeline, resourcing, and your confidence level to stakeholders.
Sample Answer
Direct answer
A credible estimate for a bounded piece of owned technical work is never a single number. It is a range built from a real decomposition of the work, with the assumptions and risk factors named out loud rather than folded silently into padding. Strong candidates separate "the work I can size confidently" from "the unknowns that could blow this up" and present both.
Structured elaboration
- Define done first. Before sizing anything, pin down what "done" actually means (what gets tested, what gets deployed, who signs off). An estimate against a fuzzy definition of done is not an estimate, it is a guess.
- Decompose into small stages. Break the work into pieces small enough that each one is individually estimable (roughly a day to a few days each), not one lump. Small stages make errors easier to catch and let you re-forecast partway through instead of waiting until the end to discover you were wrong.
- Name your assumptions explicitly. Write down what you are assuming about scope, existing tooling, data availability, and team support. These assumptions are exactly what turns out to be wrong later, so writing them down is what lets you catch it early.
- Identify the risk factors that could blow up the estimate, separately from the baseline work itself: unfamiliar technology, an external dependency you do not control, environment or data-access delays, and any stage that depends on something you have not verified yet. The biggest risk to a technical estimate is almost always one of these, not the raw coding effort.
- Estimate each stage as a range (an optimistic case if nothing goes wrong, and a likely case), then add contingency sized to the risk factors you named, rather than a flat percentage applied blindly everywhere.
- Present timeline, resourcing, and confidence as one package: the stage breakdown, the range with a stated confidence level, the top two or three named risks that could move the number, and the checkpoint at which you will re-confirm the estimate once the biggest unknown is retired.
Worked example
Take automating a regression suite. Decomposition: audit the existing manual suite and select which cases to automate (2 days), extend the automation framework (3 days), author automated tests for 30 selected cases at roughly half a day each (15 days), stabilize flaky tests and wire into CI (continuous integration, the automated pipeline that runs tests on every code change) (3 days). Baseline sum: 2 + 3 + 15 + 3 = 23 days.
The two named risk factors: the automation framework may need real rework if the underlying application's UI changes mid-project, and test-environment access could be delayed. Contingency for those two risks adds roughly 3 days, giving a likely estimate of 26 days. Optimistic case (framework needs no rework, stabilization goes smoothly): 21 days. Pessimistic case (environment access is delayed by a full week): 26 + 5 = 31 days.
What I would present to stakeholders: "roughly 5 to 6 weeks (about 26 working days) at medium confidence, with a realistic range of 21 to 31 days depending on two named risks: framework rework and environment access. I will check back in at day 10, once the framework and audit stages are done, and re-confirm or revise the range."
The same shape applies just as directly to a reporting-dashboard build for a Business Intelligence or Data Analyst: decomposition might run source-data validation (2 days), query and metric-definition build (4 days), visual build and stakeholder review cycles (5 days), and a final accuracy reconciliation against a known source of truth (2 days), for a baseline of 13 days. The named risk factors shift to data-quality gaps discovered during reconciliation and a slow stakeholder review turnaround, rather than framework rework, but the same discipline holds: present a range with a stated confidence level, name the top risks, and set a checkpoint (for example, after the query and metric-definition stage) to re-confirm the estimate rather than wait until the deadline.
Trade-offs and pitfalls
Padding the number silently instead of naming the actual risk teaches stakeholders nothing about what to watch. Giving a single point estimate as if it were a fact invites a commitment you cannot actually make good on. Not re-forecasting at a natural checkpoint means the first time anyone learns the estimate was wrong is at the deadline. And anchoring the estimate to the requester's preferred date, then reverse-engineering a plan to fit it, is the fastest way to lose credibility the next time you estimate anything.
Propose schema patterns to add auditing and change-tracking to tables for traceability. What columns and structures would you add to capture who changed a row and when, and what approach would you use for row-level history: a separate audit table, database-level change data capture, or an append-only pattern? Discuss the queryability and performance trade-offs of each history-tracking approach.
Sample Answer
Direct answer
The three realistic options for row-level change history are a separate audit table (one row per change, referencing the original table), database-level change-data-capture (CDC, reading the write-ahead log independently of the application), or an append-only pattern (the "table" itself is a log of versions, with the current state being the latest version per key); the right choice trades off write-path coupling against query convenience.
Structured elaboration
- Separate audit table (
orders_audit(audit_id, order_id, changed_by, changed_at, change_reason, old_values, new_values)), populated either by a trigger onordersor by explicit application-level writes alongside the main update. Simple to query directly ("show me the history of this order"), but a trigger-based implementation couples every write's latency to the trigger's cost, and an application-level implementation risks missing history if some code path updates the table without remembering to also write the audit row. - Database-level CDC (reading the write-ahead log or a logical-replication stream, e.g., via Debezium, entirely outside the application): captures every change regardless of which application code path made it (closing the "forgot to log it" gap), decoupled from the write's own transaction latency, but the history lives in a separate downstream system (a Kafka topic, a sink table) rather than directly queryable alongside the source table without additional plumbing.
- Append-only pattern (never
UPDATEin place; every change is a new row, and "current" is whichever row for a given key has the latest timestamp or highest version number): the history IS the table, so there's no risk of forgetting to log a change, and querying "state as of time T" is a natural filter; the trade-off is that every ordinary read of "current state" now needs a filter or a materialized "current" view to avoid scanning the entire history.
Worked example
For created_by/created_at/updated_by/updated_at as always-present columns: these answer "who last touched this row and when" cheaply for the CURRENT row, but they overwrite prior history on every update, so they are not a substitute for any of the three mechanisms above if you need to see the full sequence of past changes, only a complement to them for the common, cheaper case of "who changed this most recently."
Trade-offs and pitfalls
- The trigger-based audit table is the most common production pattern because it's the most directly queryable, but it's also the easiest to accidentally bypass: a bulk
UPDATErun directly against the database by an operator, or a data-migration script, can skip the application code path the audit-table logic assumed was the only writer, silently leaving a gap in the history. - CDC closes that "forgot to log it" gap completely (it reads the actual write-ahead log, not application intent), which is exactly why it's the more robust choice when auditability is a compliance requirement rather than a convenience feature, at the cost of the history living in a separate system that needs its own query tooling.
- The append-only pattern's "no UPDATE ever" discipline is the strongest guarantee of the three (there is structurally no way to lose history, since nothing is ever overwritten), but it pushes real complexity onto every reader that wants current state, and it requires a clear convention (a version number, or a
is_currentflag maintained carefully) to avoid every query needing to compute "which row is the latest" itself.
For a global e-commerce platform, choose appropriate data stores for these components: (a) transactional orders, (b) product catalog, (c) user sessions, and (d) product images. For each choice, justify your pick based on consistency needs, query patterns, expected scale, latency, and cost.
Sample Answer
Direct answer
Each of these four components has a distinct consistency, query, scale, latency, and cost profile, so a single "one database for everything" choice is wrong for at least two of them: transactional orders need strong consistency and transactional guarantees, the product catalog needs to be read-heavy and flexible for search and browse, user sessions need to be fast and disposable, and product images need to be stored as large blobs, not database rows.
Structured elaboration
| Component | Recommended store type | Why |
|---|---|---|
| (a) Transactional orders | A relational database with strong (ACID: atomicity, consistency, isolation, durability) transactional guarantees | Orders involve money and inventory decrement together; a lost or double-applied order write is a real business incident, so the strong consistency and multi-row transaction support of a relational engine is worth its lower write-throughput ceiling |
| (b) Product catalog | A document or search-optimized store, a document database, or a dedicated search index alongside a simpler backing store | Catalog reads vastly outnumber writes, query patterns are flexible, filter by category, attribute, free text, and schema varies by product type; eventual consistency, a new product taking a few seconds to become searchable, is a non-issue |
| (c) User sessions | An in-memory key-value store with a time-to-live (TTL) | Sessions are read and written on nearly every request, so raw speed matters most, and they are inherently disposable, a lost session just forces a re-login, which makes an in-memory store's weaker durability guarantee an acceptable trade for its latency |
| (d) Product images | Object storage, referenced by a URL or key from the catalog record | Images are large, immutable-once-uploaded blobs; storing them as database rows wastes an expensive, latency-optimized engine on cheap, bulk-optimized data, and object storage pairs naturally with a content delivery network (CDN) for fast delivery |
Justification detail per component
- Orders: consistency need is high, a double-applied order or a lost inventory decrement is a real financial and operational problem; query pattern is transactional, read-then-write within one logical operation; scale is moderate relative to catalog reads; latency tolerance is moderate, users expect an order confirmation in seconds, not milliseconds; and cost is acceptable to spend on the pricier, higher-guarantee engine precisely because order volume is the smallest of the four, so the more expensive per-operation cost is applied to the lowest-volume, highest-stakes workload.
- Catalog: consistency need is low, eventual consistency on a new listing appearing in search is invisible to users; query pattern is read-heavy and highly variable, filters, free text, sorting; scale is the largest of the four in read volume; latency needs to be low for a good browsing experience; and cost per read on a search-optimized store is low, which matters most here because this is the highest-volume read path of the four, running it through a pricier transactional engine would be the expensive mistake.
- Sessions: consistency need is minimal, losing a session is an inconvenience, not a correctness bug; query pattern is a simple key lookup; scale is very high in request volume but small in data size per session; latency needs to be the lowest of the four; and cost per gigabyte for in-memory storage is higher than disk-based storage, but session data is tiny per user and time-to-live-bounded, so total cost stays small despite the pricier storage tier.
- Images: consistency need is essentially none, an image is written once and read many times; query pattern is a simple key or URL fetch; scale is large in total bytes but simple in access pattern; latency is best served by caching close to the user; and cost per gigabyte for object storage is the cheapest of the four storage tiers, which matters because images are by far the largest total byte volume of the four components.
Worked example
A customer places an order for a product. The order write, component a, goes through a transaction that decrements inventory and creates the order record atomically, using the relational store's transactional guarantee to ensure both happen together or not at all. The product page they ordered from was served from the catalog store, component b, which returned in a few milliseconds from a search-optimized index without touching the transactional database at all, keeping catalog browsing traffic, the highest-volume read path, off the system protecting transactional correctness. Their session, component c, was checked on every single page request via a sub-millisecond in-memory lookup, cheap enough to do on every request without adding meaningful latency. The product images on that page, component d, were served from object storage through a content delivery network edge cache, never touching any database, and a regional content-delivery outage would degrade image loading without touching order processing, catalog search, or session handling at all, demonstrating the isolation benefit of separating these four concerns into four purpose-fit stores.
Trade-offs and pitfalls
- Putting everything in one relational database, a common early-stage shortcut, works fine at small scale but couples catalog read load and session read and write load to the same engine that needs to protect transactional order correctness; a catalog traffic spike from a viral product can then degrade order processing, the worst possible failure to have coupled together.
- Putting session data in a database "for durability" trades away the latency benefit sessions actually need, for a durability guarantee sessions do not actually require, a common overcorrection once teams learn to distrust in-memory stores.
- Storing images as database blobs instead of in object storage bloats the database's storage and backup size and slows every backup and restore operation, for data that gets no benefit from living in a transactional engine.
Want to create your own tailored preparation guide using our deep research?
Get Started for FreeInterview-Ready Courses
Visual-first, interactive, structured learning paths