Interview prep for a DevOps Engineer role
Sixty technical questions with model answers, spread across all fourteen domains this course teaches, plus the open-ended design questions, the behavioural questions, the questions worth asking them, and an honest plan for the last week. The point of this page is not to hand you a script to recite — a recited answer is audible from across a table. It is to make sure that when an interviewer asks why your liveness probe restarted a healthy pod, or what actually breaks when you rebuild an artifact per environment, you already have the shape of a real answer and can spend your thinking time on their system instead of on the definition.
Studying for an interview is like practising penalty kicks. You can't know which corner the goalkeeper will dive to, so there's no point memorising one perfect kick. What you practise is the run-up: the same first three steps, every time, so that when the moment arrives you're not thinking about your feet — you're thinking about the keeper. These questions are the run-up. The keeper is whoever's sitting across the table, and they'll be different every time.
This is a question bank assembled from this course's own curriculum, written as preparation practice. It is not a transcript of any real interview, not a leaked question list, not anyone's hiring rubric, and not built from a syllabus a real interviewer shared. Nobody sat an interview and wrote down what they were asked. Where this page says a topic gets "probed hard," that is this course's judgement about what its own material implies interviewers commonly dig into — an editorial call, not data from a specific hiring process, and your own experience may reasonably disagree with it.
Every model answer here is written to be adapted, not recited. Slot in your own systems, your own incidents, your own numbers. An answer that comes out word-perfect and example-free reads as memorised; the same answer grounded in something you actually did is the one that lands. And where this page says practice varies between organisations, it genuinely does — do not assert one way as universal in a room where the interviewer runs it the other way.
What the role actually gets asked
☺ Like you're 10: Most hiring processes are a few different conversations in a row, and each one is checking something different — so an answer that's perfect for one of them can be wrong for another.
Hiring processes vary enormously — by company size, by whether the role sits inside a product team or a platform team, by whether "DevOps Engineer" at that company means pipelines, means cloud infrastructure, or means the on-call rotation with a nicer title. What follows is a common shape, not a universal one. Ask the recruiter what the stages actually are; nearly all of them will tell you, and it is a perfectly normal question.
- The screen (recruiter or hiring manager, 30 minutes). This stage is filtering, not assessing. What is being checked is whether your background plausibly matches the job, whether you can describe what you've done in plain language, and whether your expectations on level, location, and on-call are compatible with theirs. The failure mode here is not being wrong — it is being vague. "I worked on the pipeline" tells them nothing; "I own the CI pipeline for eleven services, I moved us from a nightly build to per-commit, and I carry the pager for it" tells them where you sit on the DevOps definition before you've defined a single term.
- The technical deep-dive (60 minutes, an engineer). This is where the sixty questions below live. The interviewer is testing depth versus surface: whether you know why the practice exists, not just its name. The reliable tell they are listening for is whether you can name the trade-off. Anyone can say "we use blue-green"; a smaller number can say "we use blue-green because rollback speed mattered more than infrastructure cost on that service, and we accepted that a bad change still hits 100% of users at once."
- The scenario or design round (45–60 minutes, sometimes a whiteboard, sometimes a shared doc). Deliberately open-ended: "design a pipeline for X," "this deploy takes four hours and everyone dreads it, fix it." There is no single right answer and the interviewer knows it. What is being assessed is how you decompose an underspecified problem, whether you ask about constraints before designing, and whether you design the failure path as carefully as the happy path. See the scenario section for a structure that works.
- The behavioural round (45 minutes, often the hiring manager). Checking how you behave when things go wrong, because in this discipline things go wrong on a schedule. Blamelessness, ownership, how you handle disagreement, and whether you can talk about a mistake without either minimising it or performing contrition. See the behavioural section.
- Sometimes a practical exercise. A take-home (write a pipeline, write a module), a live troubleshooting session against a broken environment, or a pairing round. If you get one, treat the README and the commit history as part of the submission — this is a discipline where "I wrote down why" is a professional skill, not a nicety.
Almost every question below has a correct answer that takes fifteen seconds and a good answer that takes ninety. The difference is nearly always the same three additions: the trade-off ("this costs you X"), the failure mode ("this breaks when Y"), and the boundary ("I would not use this for Z"). If you are ever unsure how to extend an answer, extend it in one of those three directions rather than by restating the definition in different words.
The topic map: which domains get probed hardest
☺ Like you're 10: Fourteen subjects, but they don't get asked about equally — a few come up in nearly every interview and a few only come up if the job actually does that thing.
The emphasis column below is this course's judgement, based on how central each domain is to the day-to-day work of the role and how much of the rest of the material depends on it — not a measurement of any real interview. Read it as a study-order hint. A job description that mentions Kubernetes in every second line should push you to reweight it yourself; so should one that never mentions containers at all.
| Domain | Typical emphasis | What they tend to dig for | Course lesson |
|---|---|---|---|
| CI/CD Pipelines | Heaviest | The precise CI / delivery / deployment distinction, and stage ordering as a cost decision | CI/CD pipelines |
| Deployment Strategies | Heaviest | Rollback design and the readiness/liveness split, not just naming the three patterns | Deployment strategies |
| Infrastructure as Code | Heaviest | State, drift, locking — the operational problems, not the syntax | Infrastructure as code |
| Monitoring & Observability | Heavy | Whether you can alert on symptoms rather than causes | Monitoring & observability |
| Containers & Orchestration | Heavy | Pod/Deployment/Service fluency and why the isolation boundary is thinner than a VM's | Containers & orchestration |
| Version Control & Branching | Heavy | Branch lifetime as a proxy for merge risk; deploy-versus-release | Version control & branching |
| Incident Management | Heavy | Whether you have actually been on call, and what you did with the pager | Incident management |
| Measuring Success | Medium | The four DORA metrics and the Goodhart trap of chasing one | Measuring success |
| Build & Artifact Management | Medium | Build once, promote everywhere — and why a floating tag breaks it | Build & artifact management |
| Configuration Management | Medium | The provisioning/configuration boundary and push-versus-pull | Configuration management |
| Culture & Collaboration | Medium | Blameless done properly, and whether you understand Conway's Law as a design tool | Culture & collaboration |
| What Is DevOps | Opener | Usually one warm-up question; a weak answer here colours the whole hour | What is DevOps? |
| DevOps Lifecycle | Opener | Whether you treat it as a loop or as a pipeline drawn in a curve | The DevOps lifecycle |
| DevOps Toolchain | Varies | Category reasoning over vendor loyalty; how you'd choose, not what you like | The DevOps toolchain |
Sixty questions follow, grouped by domain in the order of the course, each with a difficulty marker: 🟢 warm-up — definitional fluency, you should be able to answer in under a minute without preparing; 🟡 medium — a structured answer plus a concrete example from your own work; 🔴 hard — scenario or trade-off depth, where the interviewer expects you to think out loud rather than produce a fact. Each card gives the question the way an interviewer would actually phrase it, a model answer, and where it applies, a note on what is really being checked and the common wrong answer worth avoiding. Answer out loud before reading the model answer — recognising an answer and producing one are different skills, and only the second one is tested.
What Is DevOps — 4 questions
☺ Like you're 10: The opening questions about what DevOps even means — easy to answer badly by reciting a buzzword, easy to answer well by naming the problem it was invented to fix.
🟢 Q1 · Define DevOps
As they'll ask it: "So — how would you define DevOps? What does it actually mean to you?"
Model answer. DevOps is a set of practices for closing the gap between the people who write software and the people who keep it running. It is not a job title, not a tool, and not a team. The problem it was invented to solve is structural: Dev is typically rewarded for shipping change and Ops is typically rewarded for avoiding change-caused incidents, so with no shared accountability you get the pattern the community named the wall of confusion — work thrown over it in one direction, risk thrown back in the other. The fix is shared ownership, summarised at Amazon as "you build it, you run it": the team that writes a service also deploys it, monitors it, and carries the pager for it, so release risk and operational risk land on the same people.
Historically the turning point most people point to is John Allspaw and Paul Hammond's 2009 Velocity talk on ten-plus deploys a day at Flickr, after which Patrick Debois organised the first DevOpsDays in Ghent and the term stuck. But the definition that actually does work day to day is CALMS — Culture, Automation, Lean, Measurement, Sharing — because it lets you test any proposed "DevOps improvement" against something concrete: which letter does this serve?
What they're really checking: whether you understand DevOps as an incentive-and-ownership problem or as a synonym for "we use Jenkins." A candidate who defines it purely in terms of tooling will usually also design purely in terms of tooling.
Common wrong answer: "DevOps is the automation of the software delivery process using CI/CD tools." That is one pillar — Automation — of five, described as if it were the whole thing. Automating a broken handoff just makes a dysfunctional handoff faster.
🟢 Q2 · CALMS
As they'll ask it: "Have you come across CALMS? Walk me through it."
Model answer. CALMS started as CAMS — coined by John Willis and Damon Edwards — and Jez Humble later added the L for Lean. The five letters: Culture — shared ownership and blameless postmortems rather than blame-seeking after an incident. Automation — replacing manual, error-prone handoffs with pipelines and code. Lean — small batch sizes and limited work in progress, borrowed from the Toyota Production System, so a failed change is small and cheap to diagnose instead of large and catastrophic. Measurement — instrumenting both the pipeline and the system in production so decisions run on data. Sharing — knowledge, tooling, and incident learnings crossing team boundaries by default.
The part worth adding is that none of the five works alone, and the failures are predictable. Automation without Culture makes a bad handoff faster. Measurement without Sharing produces dashboards one team looks at. Lean without Automation means you want small batches but can't ship them cheaply. I use it as a diagnostic: when someone proposes a change, asking which letter it serves usually reveals within a minute whether it's a genuine improvement or a rebrand.
What they're really checking: that you have a framework rather than a list of opinions — and specifically that "Culture" is not an afterthought you tack on at the end.
🟡 Q3 · The wall of confusion
As they'll ask it: "In your experience, why do Dev and Ops teams end up in conflict? What causes it?"
Model answer. It is almost never a personality problem, which is why reorganising the people rarely fixes it. It's an incentive problem. Developers are measured and promoted on shipped features and release velocity; operations teams are measured on uptime, time to recovery, and change failure rate — metrics that get worse when releases get more frequent. Give two groups opposing measures and no shared accountability and you get exactly what you'd predict: Dev finishes a build, files a ticket and moves on; Ops, unfamiliar with the change and holding all of the blast radius if it breaks, treats every release as a threat and adds friction — change advisory boards, freeze windows, manual sign-off gates.
The friction is a rational response to the incentives, which is the part people miss. Ops isn't being obstructive; it is optimising for the thing it's graded on. So the fix has to change the grading, not the attitude — shared on-call, shared metrics, and the same team owning both the code and the pager. Once the person who writes the bad query is the person paged at 2 a.m. by the bad query, the design conversation changes on its own.
What they're really checking: whether you can reason about organisational incentives, because a DevOps engineer who can't will keep proposing tooling fixes for structural problems.
Common wrong answer: "Ops teams are resistant to change." It blames the people rather than the system, which is precisely the reflex a blameless culture exists to train out — and an interviewer who has been on the ops side of that wall will hear it clearly.
🟡 Q4 · Is a DevOps team an anti-pattern?
As they'll ask it: "We're thinking about standing up a dedicated DevOps team. Good idea?"
Model answer. It depends entirely on what the team is chartered to do, and the honest answer starts by asking. If the charter is "all deployments and all infrastructure changes route through this team," then no — that builds a third silo directly on top of the first two, complete with its own backlog and its own handoff queue, and within a year you've recreated the exact ticket-and-wait pattern DevOps was invented to remove, just with a friendlier name on the door. That's the most common real-world failure mode, and it usually arrives disguised as a well-meaning reorg.
If the charter is instead "build and run the paved road — the shared pipeline templates, the deployment tooling, the observability stack — so every product team can self-serve," then yes, that's a platform team and it's how "you build it, you run it" stays sustainable rather than becoming every team reinventing deployment machinery. The test I'd apply: does this team make other teams faster without being in their path? If product teams have to wait on them, it's a silo. If product teams can ship at 4 p.m. on a Thursday without asking, it's a platform. The platform engineering deep-dive covers where that boundary usually settles.
What they're really checking: often, that you'll be honest about a decision they have already made. Answer the principle, not the politics — but do ask what the charter is before pronouncing.
Common wrong answer: a flat "yes, that's an anti-pattern, DevOps is a culture not a team." It's a slogan, and it ignores that platform teams demonstrably work. The distinction is the charter, not the org chart box.
DevOps Lifecycle — 3 questions
☺ Like you're 10: The eight-stage loop everyone draws — and the one arrow most people forget, which is the only thing that makes it a loop at all.
🟢 Q5 · Walk the lifecycle
As they'll ask it: "Take me through the DevOps lifecycle. What happens at each stage?"
Model answer. Eight stages, drawn as an infinity loop rather than a line specifically to signal that Deploy is not the finish line. Plan — decide what to build, informed by both business priority and production reality. Code — turn that into a change, on trunk or a short-lived branch. Build — turn source into a reproducible, versioned artifact. Test — a layered suite that gates promotion. Release — declare a specific, already-tested artifact fit to ship and version it. Deploy — move that artifact into a live environment with minimal risk. Operate — keep it running, scaled, and correctly configured under real load. Monitor — observe what it actually does and turn that into signal.
What I'd emphasise is that Release and Deploy are genuinely distinct stages, not one stage written twice: Release is the decision that an artifact is fit to ship, Deploy is the mechanics of getting it live. Teams that collapse them lose the ability to deploy without releasing, which is exactly what feature flags buy back.
What they're really checking: baseline vocabulary, and whether you say "Release and Deploy are the same thing" — which quietly reveals you haven't worked with flags or progressive delivery.
🟡 Q6 · The arrow that matters
As they'll ask it: "Which part of that loop do teams most often get wrong?"
Model answer. The arrow from Monitor back to Plan. Seven of the eight arrows just describe a delivery pipeline — Plan feeds Code, Code feeds Build, and so on — and that much is true of any structured process, DevOps or not. The eighth arrow is what makes it a lifecycle instead of a lifecycle-shaped pipeline, and it is the one teams skip when they adopt the tooling without the practice.
Concretely, closing that arrow means production telemetry is a direct input to backlog prioritisation, not a separate concern owned by someone else. An error-budget burn becomes a Plan item with the same priority mechanics as a feature request. An alert that pages the same service three times in a sprint becomes a Plan item to fix the root cause, not a rota change. A worsening p99 trend becomes a Plan item to profile before it becomes an incident. Without it, Monitor degenerates into a dashboard nobody acts on and Plan degenerates into a backlog driven entirely by feature requests, with zero signal from what's actually breaking. In an interview I'd give the concrete version: the specific recurring alert that became a ticket, and what the ticket changed.
What they're really checking: whether you've experienced the loop closing, or only seen the diagram. Almost everyone can name the eight stages; far fewer can say what the feedback arrow costs to actually implement.
🟡 Q7 · Where the stage boundaries really sit
As they'll ask it: "In a real team, do those eight stages actually stay separate?"
Model answer. No, and the diagram is misleading about it. Build and Test collapse into one automated step in practice — a single CI run that compiles and then runs the suite, with no human between them and no meaningful moment where the build "exists" but hasn't been tested. Operate and Monitor overlap continuously rather than sequencing. And in a continuous-deployment setup, Release and Deploy also collapse: the release decision is made by the pipeline passing, so there's no separate stage where a human declares fitness.
What stays genuinely separate is Plan, because it involves a decision that isn't automatable, and Code, because it's the only stage where the change is created rather than transformed. The reason to know this is that stage boundaries are where handoffs and queues form, and every queue adds latency — so knowing which boundaries are real is knowing where to look for delay. If a change is code-complete on Tuesday and live on Friday, the three days are sitting in a boundary somewhere, and the boundary is usually a human gate rather than a technical one.
What they're really checking: whether your knowledge is diagram-shaped or experience-shaped. Anyone who has actually run a pipeline knows Build and Test are one job in the YAML.
Culture & Collaboration — 4 questions
☺ Like you're 10: The people questions — and they're not the soft part of the interview, they're the part where a wrong answer says the most about you.
🟢 Q8 · Blameless postmortems
As they'll ask it: "What makes a postmortem blameless, and does blameless mean nobody's accountable?"
Model answer. Blameless means the review separates two questions that get tangled together: "what broke and why" and "whose fault is it." It answers the first and deliberately does not ask the second, because the second one makes people withhold the information the first one needs. If admitting a near-miss gets you punished, people stop admitting near-misses, and the organisation loses its earliest and cheapest warning system.
Blameless does not mean consequence-free or accountability-free, and I'd say that explicitly, because it's the objection every sceptical manager has. The team is still expected to act on what the review reveals, and the review still produces owned, dated follow-up actions rather than a feeling of closure. What changes is the target of accountability: the system that let a single mistyped command take production down is accountable, not the engineer who typed it. In practice a good review reconstructs a timeline with timestamps, asks what information each person had at the moment they made each decision, and treats "an engineer did the obvious thing and it was catastrophic" as a design defect rather than a training defect.
What they're really checking: whether you'll be safe to have in a room after an outage. The way a candidate describes someone else's mistake in this answer is often the most revealing thirty seconds of the interview.
Common wrong answer: "Blameless means we don't point fingers." True but hollow — it doesn't explain the mechanism, and it invites the follow-up "so nobody's responsible?" that you then have no answer to.
🟡 Q9 · Westrum's typology
As they'll ask it: "Is there any evidence that culture actually affects delivery performance, or is that just a nice thing to say?"
Model answer. There is, and it's one of the more useful findings to be able to cite. Sociologist Ron Westrum classified organisations by how information flows through them into three types. A pathological organisation is power-oriented: information is hoarded, messengers who bring bad news are punished, and failure triggers a search for someone to blame. A bureaucratic organisation is rule-oriented: information moves through official channels, responsibility is siloed by department, and failure triggers a search for the policy that was violated. A generative organisation is performance-oriented: information flows freely because the goal is the mission, messengers are rewarded for surfacing problems, and failure triggers inquiry into what happened rather than who did it.
The DORA / Accelerate research adopted this as a construct and found that teams scoring closer to generative had statistically better software delivery and organisational performance — higher deployment frequency, lower change failure rate, faster recovery. That's the part worth citing, because it moves culture from "nice to have" to "correlated with the numbers you're already being measured on." The mechanism is not mysterious: a generative culture is what makes blameless postmortems actually blameless instead of a euphemism, and blameless postmortems are what make an organisation learn from failures instead of hiding them.
What they're really checking: whether you can argue for cultural investment in terms a sceptical engineering manager will accept — evidence rather than sentiment.
🟡 Q10 · Conway's Law
As they'll ask it: "Have you heard of Conway's Law? How does it show up in real systems?"
Model answer. Melvin Conway's 1967 observation: organisations which design systems are constrained to produce designs that copy the communication structures of those organisations. Practically, if three teams barely talk to each other, you get a system of three loosely-integrated modules with a communication problem baked permanently into their interfaces — regardless of what the architecture diagram claims. Communication paths become API boundaries whether or not anyone designed them that way.
The useful part is the inverse. The reverse Conway maneuver turns the observation into a design tool: instead of letting the existing org chart accidentally dictate the architecture, you restructure teams around the architecture you actually want and let Conway's Law do the work. Want a clean boundary between checkout and inventory? Put them on separate teams with a defined API contract, rather than one team juggling both with tribal knowledge as the interface. Want a shared platform layer instead of every team reinventing deployment tooling? Stand up a platform team and give everyone the same paved road. Team Topologies by Skelton and Pais builds a whole team-design framework on this, naming stream-aligned, platform, enabling, and complicated-subsystem teams as the reusable shapes.
What they're really checking: senior signal. Junior candidates describe Conway's Law as a curiosity; senior ones describe it as something they've deliberately used or been defeated by.
🔴 Q11 · The real cost of "you build it, you run it"
As they'll ask it: "We want product teams to own their own on-call. What could go wrong?"
Model answer. The model is right and the costs are real, so I'd name them rather than sell past them. Werner Vogels' original argument at Amazon was about feedback loops: when the developer who wrote the bad query is the one woken up by it, the underlying design gets fixed fast, because the pain and the ability to fix it live in the same person. Split ownership removes that loop and reliably produces systems that are easy to ship and miserable to operate.
What it costs: engineers now need operational skills a pure-development role never required — reading dashboards, debugging production, understanding deployment mechanics — and that's a real training investment, not an assumption. On-call is a genuine burden that has to be compensated and rotated fairly, or the model burns people out and you lose the engineers instead of the incidents. And a team of four cannot sustain a 24/7 rotation without someone being on call every fourth week forever, which is how good people leave.
So the things I'd want in place before flipping the switch: a platform or SRE function providing the paved road so each product team isn't rebuilding observability and deployment machinery from scratch; alerting that's already been pruned to actionable, symptom-based pages, because handing a team a noisy pager is handing them a reason to hate the model; a clear escalation path so a lone on-call engineer at 3 a.m. is never actually alone; and enough people in the rotation that the maths works. The on-call culture deep-dive goes further into what sustainable looks like.
What they're really checking: whether you'll advocate for a practice without acknowledging what it costs the people who have to live with it. This is often asked by a manager who has seen a rollout of this go badly.
Measuring Success — 4 questions
☺ Like you're 10: The four numbers that tell you whether a team is actually good at shipping — and the ways people cheat them.
🟢 Q12 · The four DORA metrics
As they'll ask it: "How would you measure whether a team is doing DevOps well?"
Model answer. The four DORA metrics, from the research program founded by Nicole Forsgren, Jez Humble and Gene Kim and published in Accelerate. Two measure throughput: deployment frequency — how often the organisation successfully releases to production, expressed as a rate so teams of different sizes are comparable — and lead time for changes — elapsed time from a commit landing on trunk to that same code running in production. Two measure stability: change failure rate — the percentage of production deployments that cause degraded service and need remediation, so failed deploys divided by total deploys — and time to restore service — elapsed time from a production incident being detected to service being restored, whether by a fix, a rollback, or a mitigation.
The reason these four rather than any other four is that they survived factor analysis out of dozens of candidates as the ones that actually predict delivery and organisational performance. And they're a single scorecard, not four independent dials — reading any one in isolation is how they get misused. Note also that lead time deliberately starts at the commit, not at the idea; idea-to-commit is a product-discovery question DORA treats separately, and conflating the two makes a delivery problem look like an engineering problem when it might be a prioritisation problem.
What they're really checking: that you measure delivery rather than activity. If your instinct is story points or lines of code, this question finds it immediately.
🟡 Q13 · Speed versus stability
As they'll ask it: "Surely if you deploy more often you break things more often. How do you square that?"
Model answer. The finding that made Accelerate required reading is that you don't have to square it, because elite performers don't trade one for the other — they deploy far more frequently than low performers and fail less often and recover faster. That contradicts the intuition baked into most change-approval processes, which slow deployment down in the name of safety.
The mechanism isn't a shortcut, it's batch size. Small, frequent, reversible changes are individually lower-risk than large, infrequent, batched ones. A single config change deployed alone is easy to reason about and easy to roll back; twenty commits from three teams batched into one Friday release is not — and when it breaks, you don't even know which of the twenty did it. So frequency isn't the cause of stability; both are downstream of the same practices: trunk-based development, automated testing, and deployment strategies that support fast rollback. Throughput and stability aren't opposite ends of a dial, they're correlated in the same direction because they share causes.
The practical consequence for an interview answer: if someone wants to improve stability, "deploy less often" is usually the wrong lever, because it increases batch size. The right levers are test automation, smaller changes, and a faster rollback path.
What they're really checking: whether you can defend high deployment frequency to a risk-averse stakeholder, which is a large part of this job in many organisations.
Common wrong answer: "It's a trade-off — you pick where you want to sit on the speed/safety spectrum." It sounds balanced and mature and the research says it's wrong; treating it as a dial is exactly the belief that produces quarterly release trains.
🟡 Q14 · Actually computing them
As they'll ask it: "Say we've never measured any of this. Where would the numbers even come from?"
Model answer. Most of it comes from data you already have. Deployment frequency and lead time come out of the CI/CD system: deploy events give you the frequency, and joining a deploy event back to the commit timestamps in the changeset gives you lead time — GitHub Actions, GitLab CI, and Jenkins can all export enough to do this, and the join key is the commit SHA the deploy shipped.
The two stability metrics are harder, because they need something the pipeline doesn't know: which deployments caused an incident. That means linking the deploy log to whatever the team uses for incident tracking — a PagerDuty or Opsgenie timeline, or even a manually maintained incident register at first. I'd be honest in the interview that this is where measurement programmes usually stall, and that the first version is often a spreadsheet where the on-call engineer tags the incident with the deploy they think caused it. That's imprecise, and it's still enormously better than nothing, because the trend is the useful part rather than the absolute value.
Two implementation notes I'd raise. Measure on a rolling window — 30 or 90 days, not a single release — because a single bad week otherwise reads as a regression. And decide up front what counts as a deployment: if "deploy" means a config push as well as an application release, say so and stay consistent, because the definition drifting is how a dashboard quietly stops meaning anything.
What they're really checking: whether you can turn a principle into an implementation plan, and whether you'll admit the messy part rather than describing an idealised pipeline nobody has.
🔴 Q15 · When the metric becomes the target
As they'll ask it: "Leadership has set a target: double deployment frequency this quarter. How do you respond?"
Model answer. I'd flag it as a Goodhart's Law risk before agreeing to it — when a measure becomes a target it ceases to be a good measure, and deployment frequency is unusually easy to hit dishonestly. A team told to double it can split one meaningful release into ten trivial ones: a whitespace change, a comment update, a config no-op, each counted as a deploy. The dashboard goes up, lead time and failure rate stay flat or get worse, and engineers now spend time manufacturing deploys instead of shipping value.
What I'd propose instead: treat all four metrics as one scorecard and set the target on the scorecard, not the single number. If deployment frequency rises while lead time falls and change failure rate holds steady or improves, that's real. If frequency rises alone, it's being gamed. Then work the practices underneath rather than the number on top — batch size, test automation, trunk-based development, rollback speed — because the metrics are diagnostic signals for those practices, not things you can hit directly.
I'd also ask what problem the target is meant to solve, because "double deployment frequency" is usually a proxy for something more specific — features taking too long to reach customers, or too much risk per release. If it's the first, lead time is the honest metric; if it's the second, change failure rate and restore time are. Naming the real goal usually gets you a better target than arguing about the wrong one.
What they're really checking: whether you'll push back constructively on a bad instruction from above. The answer they don't want is either silent compliance or flat refusal.
Version Control & Branching — 5 questions
☺ Like you're 10: How long you're allowed to work on your own before showing everyone — and why that one answer changes almost everything downstream.
🟢 Q16 · Trunk-based, GitFlow, GitHub Flow
As they'll ask it: "What branching strategies have you worked with, and what's the difference between them?"
Model answer. All three answer one question: how much work sits outside the main line before it merges back in?
Trunk-based development. Everyone merges into a single branch — main — at least daily, often several times a day. Feature branches, where used, live hours rather than days. Work that isn't ready for users ships anyway, hidden behind a feature flag. This is what Google and Meta run internally at scale, and it's the strategy DORA correlates most strongly with elite delivery performance.
GitFlow. Vincent Driessen's 2010 model: long-lived develop and main branches plus supporting feature/*, release/* and hotfix/* branches. A release branch is cut from develop, stabilised independently, then merged into both main and back into develop. Designed for software shipped in discrete, infrequent versions — desktop installers, firmware, anything with a formal release calendar.
GitHub Flow. The middle ground: one long-lived always-deployable main, short-lived feature branches, a pull request reviewed and CI-tested and merged back, typically within a day or two. No develop branch, no scheduled release branches.
The point I'd add is that the line between GitHub Flow and trunk-based is branch lifetime and flag discipline, not tooling. A team practising GitHub Flow with same-day merges and flags around incomplete work is doing trunk-based development; the label is less informative than the branch age.
What they're really checking: whether you have an opinion grounded in consequences. "We used GitFlow" is fine; "we used GitFlow and here's what it cost us at three deploys a week" is the answer they remember.
🟡 Q17 · When is GitFlow the right call?
As they'll ask it: "Would you ever choose GitFlow today?"
Model answer. Yes, but narrowly. GitFlow remains defensible for software shipped as discrete versions that customers install and then live with — desktop applications, mobile releases gated by an app store review, firmware, on-premise products where several versions are supported simultaneously and you genuinely need a maintained release/2.3 branch to backport a security fix into. Those situations have a real "version" concept, and GitFlow's structure exists to serve exactly that.
Where it actively fights you is a service that deploys several times a day. Long-lived branches accumulate drift; drift produces large, conflict-prone merges; large merges are slow to review and risky to land. And the release branch models a ceremony a continuously-deployed service doesn't have. The underlying principle is worth stating plainly: branch lifetime is a proxy for merge risk. A branch open two hours diverges from main by a handful of commits; a branch open two weeks diverges by everything everyone else merged that fortnight. Trunk-based development's real claim isn't "no branches" — it's branches short enough that conflicts stay rare and small.
What they're really checking: nuance. A candidate who says "GitFlow is obsolete" is repeating a blog post; a candidate who names the shipping model that still justifies it has thought about it.
🟡 Q18 · Deploy versus release
As they'll ask it: "What's a feature flag for? Isn't it just an if-statement?"
Model answer. Mechanically it is an if-statement — a runtime conditional, usually backed by a config service or a flag platform, deciding whether a code path executes for a given user, cohort, or environment. What it buys is a separation that isn't otherwise available: deploying means the new code is running in production; releasing means users can see or use it. Without flags those two events are forced to happen at the same moment, which is precisely why teams historically batched changes into large, risky releases.
With flags you can deploy dark code continuously — merged, tested, running, switched off — and release later with a config change instead of a deploy: flip for 1% of traffic, watch error rate and latency, ramp to 100%, or flip back off instantly. There's no redeploy, no revert commit, no waiting on a build. That makes a flag flip the single fastest "undo" available to you, faster than any deployment strategy, because it isn't a deployment at all. It's also the thing that makes trunk-based development safe: incomplete work can live on main because it isn't reachable.
The cost is code complexity rather than infrastructure cost. Every live flag is a conditional both states of which have to work and ideally be tested, and a flag left in place after full rollout is dead weight a future engineer has to reason around. I'd treat flag removal as a required follow-up ticket, not optional cleanup — a flag found a year later still gating logic nobody remembers the other branch of is a genuinely common source of confusing incidents. The progressive delivery deep-dive covers the lifecycle.
What they're really checking: whether you understand the deploy/release distinction, which is the conceptual key to most of modern delivery — and whether you'll mention flag debt unprompted, which signals you've actually lived with them.
🟢 Q19 · Commit hygiene and Conventional Commits
As they'll ask it: "Do you care about commit messages? Does it actually matter?"
Model answer. Two habits do most of the work. Commits should be atomic — one logical change each, every commit leaving the codebase in a working state — because that's what makes git bisect able to binary-search history for the commit that introduced a regression without landing on a broken intermediate. And messages should say why, not restate the diff: "fix off-by-one in pagination cursor causing last page to drop" is useful in a blame six months later; "fix bug" is not.
Conventional Commits standardises the first line into <type>(<scope>): <description>, with types like feat, fix, docs, refactor, test, chore, plus a ! or a BREAKING CHANGE: footer. The reason this is more than style is that tools parse it: semantic-release and similar read the commit types since the last tag to compute the next semantic version automatically — a fix bumps patch, a feat bumps minor, a breaking change bumps major — and generate the changelog, removing a manual step from every release. So the convention isn't tidiness for its own sake; it's making history machine-readable so releases stop depending on someone remembering to bump a number.
What they're really checking: whether you see version control as an operational tool or as a backup system. The bisect answer is the one that signals the former.
🟡 Q20 · GitOps
As they'll ask it: "What's GitOps, and how is it different from just running your deploys from CI?"
Model answer. GitOps extends "git is the source of truth" from application code to infrastructure and deployment state. The desired state of a cluster or environment — which images run, how many replicas, which config values — is described declaratively and stored in a git repository, and a reconciling agent (Argo CD and Flux are the two dominant tools) continuously compares that declared state against the live state of the cluster and converges the two, applying changes automatically or flagging drift when they diverge.
The difference from CI-driven deploys is the direction and the continuity. A CI pipeline pushes: it runs kubectl apply at the end of a job, and then nothing watches. GitOps pulls: an agent inside the target environment watches the repo and reconciles on a loop, forever. Two consequences follow. First, drift gets corrected rather than merely happening — someone who hand-edits a live resource sees it reverted on the next reconciliation, which is either exactly what you want or a surprise you need to have designed for. Second, the credentials point the other way: the cluster reads from git rather than CI holding cluster-admin credentials, which shrinks a meaningful piece of your blast radius.
The practical effect is that a console click or a manual apply stops being how production changes — a pull request against the state repository is — so every infrastructure change inherits the same review, audit trail, and revert-by-git revert properties that application code already had.
What they're really checking: whether you can distinguish push from pull reconciliation, since that distinction is the whole substance of the term and the part marketing usually skips.
Common wrong answer: "GitOps means your infrastructure is in git." Necessary but nowhere near sufficient — infrastructure has been in git since IaC existed. The reconciling agent is the new part.
CI/CD Pipelines — 5 questions
☺ Like you're 10: The most misused three letters in the field, and the questions that find out whether you actually know which of them your last team did.
🟢 Q21 · The three C's
As they'll ask it: "Continuous integration, continuous delivery, continuous deployment — what's the difference?"
Model answer. Continuous integration means developers merge small changes into a shared trunk frequently — multiple times a day, not once a week off a long-lived branch — and every merge automatically triggers a build and a test run. It traces back to Kent Beck's Extreme Programming and was named and popularised by Martin Fowler. Its promise is narrow and worth stating narrowly: it tells you within minutes whether the trunk still builds and still passes its tests. It says nothing about releasing anything to anyone.
Continuous delivery extends that: every change that passes the pipeline produces a release candidate automatically verified and proven deployable to production at any time. The pipeline builds the confidence; a human still decides when to release — often one click, but a deliberate decision every time. Humble and Farley's strict claim is worth quoting because interviewers like it: if your main branch isn't always in a releasable state, you don't have continuous delivery yet, no matter how much automation you've bolted on.
Continuous deployment removes that last human gate. Every change passing every stage ships to production automatically. The rule worth memorising: all continuous deployment is continuous delivery, but not all continuous delivery is continuous deployment. Delivery is the foundation — always releasable; deployment is delivery with the release button wired to the pipeline instead of to a person.
What they're really checking: precision. This is the single most common place a candidate uses "CI/CD" as one undifferentiated word and gets caught by a follow-up.
Common wrong answer: "CD stands for continuous deployment, which is when you automate the deploy." It collapses two distinct practices, and the interviewer will immediately ask which one your last team actually had — a question you can no longer answer.
🟡 Q22 · Pipeline anatomy
As they'll ask it: "Walk me through the stages of a pipeline you've built. Why in that order?"
Model answer. A common ordering, and the order is a cost decision rather than a convention: lint (static analysis, seconds, catches typos before anything else bothers to look), unit test (fast isolated tests, a minute or a few), build (compile or assemble into a runnable artifact such as a container image), integration test (the built artifact against real or realistic dependencies), security and dependency scan (SAST on the code, software-composition analysis on the dependency tree for known CVEs), package (tag and publish the verified artifact to a registry, immutable and traceable back to the commit), deploy to staging, smoke test (a short shallow check — does the health endpoint answer, can a user log in — not a regression suite), then deploy to production.
Two things about the ordering. It runs cheapest and fastest checks first, so a broken change gets rejected before the pipeline spends ten minutes building something that was never going to pass. And the security scan sits after build specifically because it needs an artifact to scan — the ordering isn't purely about speed, it's about dependency too.
The detail I'd make sure to say out loud: the same artifact moves through staging and production unmodified. Nothing gets rebuilt between environments. Rebuilding per stage means you're no longer testing the thing you're about to ship, you're testing a cousin of it.
What they're really checking: whether you've built one or only used one. The "why that order" follow-up is the actual question; the stage list is the setup.
🟢 Q23 · Pipeline-as-code
As they'll ask it: "Why does the pipeline definition live in the repo rather than in the CI server's UI?"
Model answer. Because a pipeline configured through a web UI has no history, no code review, and no way to answer "what changed between last Tuesday's green build and today's red one." Pipeline-as-code means the definition is a plain text file — .github/workflows/*.yml for GitHub Actions, .gitlab-ci.yml for GitLab CI, a Groovy Jenkinsfile, azure-pipelines.yml for Azure Pipelines — checked into the same repository as the application it builds, versioned, diffed, and reviewed exactly like the code it protects.
Three concrete benefits follow. A pull request changes the pipeline, so a reviewer reads the diff before it takes effect. git blame tells you who added that flaky-test retry flag and when. And the pipeline branches with the code: a feature branch can carry a temporary pipeline tweak without affecting what every other branch runs, and reverting a bad pipeline change is git revert rather than an email to whoever has admin on the CI server. It's the same argument as infrastructure as code, applied one layer up — a diffable, reviewable, revertible record beats a settings page.
What they're really checking: that you treat delivery machinery as production software subject to the same disciplines, not as configuration someone fiddles with.
🔴 Q24 · The pipeline nobody watches
As they'll ask it: "Our pipeline takes about 45 minutes and people have stopped watching it — they push and go to lunch. How would you approach that?"
Model answer. I'd separate two problems, because they need different fixes: the pipeline is too slow, and the feedback is arriving too late to act on. The second one is the more damaging.
First I'd measure rather than guess — get per-stage timing over a few weeks and find where the 45 minutes actually goes. It's usually concentrated: a full dependency install on every run because the layer cache is being invalidated, an end-to-end suite doing work integration tests could do, tests running serially that could shard, or an entire suite re-running for a docs-only change.
Then I'd apply the fast-feedback principle deliberately. The rule is fail fast, fail loud, fail early: put the cheapest, quickest checks first so a broken change is rejected in ninety seconds rather than forty-five minutes. Concretely, that usually means a fast lane that runs lint and unit tests and reports within a couple of minutes, with the slower stages continuing behind it. Caching dependencies and build layers properly. Sharding the slow suite across parallel runners. And auditing the end-to-end tests, because a thin tip on the test pyramid is a deliberate choice rather than an accident — see testing in the pipeline.
I'd also check "fail loud" is actually true, because a 45-minute pipeline whose failures land in a channel nobody reads is worse than it looks. A failed stage must stop the pipeline outright and notify the person who broke it immediately. There is no such thing as a soft failure in a pipeline gate — a stage either passes and the change proceeds or it fails and the change stops. If anyone has added a "continue on error" to keep the board green, that's the first thing I'd remove.
And I'd say plainly what the cost of not fixing it is: at 45 minutes, engineers context-switch away, so a failure gets picked up an hour later against a trunk that has moved on. That inflates lead time and it inflates change failure rate, because fixes get rushed.
What they're really checking: whether you measure before optimising, and whether you notice the human problem behind the technical one. Candidates who jump straight to "add more runners" have answered half the question.
🟡 Q25 · Where the human gate sits
As they'll ask it: "Would you argue for full continuous deployment here? What would have to be true first?"
Model answer. The boundary between delivery and deployment is one mechanism, not a philosophy: GitLab CI's when: manual on a job, GitHub Actions' required reviewers on a protected environment, a Jenkins input step, Argo CD's manual-versus-automated sync policy. All four are the same idea — the pipeline pauses at the production-deploy stage and waits for a person, or it doesn't. Removing that one gate is what turns continuous delivery into continuous deployment; nothing else changes.
What I'd want true before removing it: a test suite the team actually trusts, so a green pipeline means something; automated rollback wired to a metric threshold rather than to a human noticing; a deployment strategy that limits blast radius, canary or flags, so a bad change reaches a fraction of users rather than all of them; and observability good enough to detect a regression within minutes rather than at the next standup. Absent those, removing the gate doesn't make you faster, it makes you faster at shipping regressions.
I'd also name where I would keep the gate on purpose, because that's the honest part. Regulated environments where a named approver is a compliance requirement. Changes touching data migrations, where the rollback isn't symmetric. And genuinely, teams new to this — the gate is a reasonable training wheel while trust in the suite is being built, as long as everyone agrees it's temporary rather than permanent. Many teams that deploy continuously still control what users see with feature flags anyway, which is often the better conversation: keeping the deploy automatic and moving the human decision to the flag.
What they're really checking: whether you treat continuous deployment as a maturity outcome with prerequisites or as a badge to chase. The prerequisites are the answer.
Build & Artifact Management — 4 questions
☺ Like you're 10: Build the thing once and carry that exact same thing all the way through — the questions here are about what goes wrong when you don't.
🟢 Q26 · Build once, promote everywhere
As they'll ask it: "Our pipeline rebuilds the app for each environment with environment-specific config baked in. Any problem with that?"
Model answer. Yes, and it's a real one rather than a style preference. The principle is build an artifact exactly once and promote that literal artifact through every environment — dev, staging, production — rather than rebuilding from source at each stage. The artifact that passed integration tests in staging should be, byte for byte, the artifact running in production.
What rebuilding costs you is the meaning of your own test results. Even a build you believe is reproducible is only a belief until it's proven: between the staging build and the production build a dependency resolver can silently pick up a newer transitive version, a base image can get repatched underneath you, or a compiler flag can differ. Any of those makes "it passed staging" stop saying anything reliable about what's actually in production. The whole point of a staging environment is to test the thing you're going to ship, and rebuilding means you tested a cousin of it.
The fix for environment-specific config is to inject it at runtime rather than bake it at build time — environment variables, a mounted config map, a config service — so one artifact runs everywhere and the difference between environments is data rather than bytes. Promotion then becomes adding a tag to an existing digest: build once, tag with the immutable commit SHA, and add staging-verified and then prod as pointers to that same digest. Only the tags move.
What they're really checking: whether you can explain why a common convenience is actually a correctness bug. This one comes up constantly because so many real pipelines get it wrong.
🟡 Q27 · Reproducible builds
As they'll ask it: "What makes a build reproducible, and what tends to break it?"
Model answer. A reproducible build is one where compiling the same source at the same commit with the same toolchain produces byte-for-byte identical output every time — same hash, regardless of who ran it or when. It sounds trivially true until you look at what quietly breaks it: embedded build timestamps, filesystem iteration order leaking into a serialised map, absolute paths baked into debug symbols, and a dependency resolver picking up a newer patch release because a version range wasn't pinned.
The disciplines that get you there are a short list: pin every dependency to an exact version via a lockfile rather than a floating range; build inside a hermetic image pinned by digest rather than a mutable tag; normalise or strip timestamps, for which SOURCE_DATE_EPOCH is the de facto environment variable most toolchains now honour; and sort any iteration order that affects output.
The framing worth adding is that the Reproducible Builds project treats this as a security property, not just a QA nicety: if two independent parties rebuild a package from the same source and get an identical hash, that is evidence nothing was altered between source and binary — a supply-chain guarantee that code review alone cannot give you. That connects it directly to provenance and signing, covered in supply-chain security.
What they're really checking: depth. Most candidates can define reproducibility; far fewer can name three specific things that break it, which is what distinguishes reading about it from debugging it.
🟢 Q28 · Semantic versioning
As they'll ask it: "What does semantic versioning actually promise a consumer?"
Model answer. It turns MAJOR.MINOR.PATCH from an incrementing counter into a contract. Bump MAJOR on a backwards-incompatible change to the public API; MINOR when you add backwards-compatible functionality; PATCH for a backwards-compatible bug fix. So a consumer seeing a MINOR bump knows they can upgrade without touching their own code, and a MAJOR bump is the signal to read the changelog before moving the pin. Pre-release and build-metadata suffixes extend it — a release-candidate suffix, or metadata that doesn't affect precedence.
The value is that it's machine-readable rather than just a human convention. Dependency resolvers use the MAJOR boundary to decide what an unpinned upgrade is allowed to touch — a caret range meaning "anything below the next major." And it composes with Conventional Commits: tooling reads the commit types since the last tag, maps fix to patch and feat to minor and a breaking-change footer to major, and cuts the tag without anyone typing a version number by hand.
The honest caveat, if they push: semver is a promise, and promises get broken. Plenty of ecosystems have shipped breaking changes in a minor release by accident. So it informs how you pin dependencies, it doesn't replace testing the upgrade.
What they're really checking: whether you think about the consumers of what you publish, which is the mental shift from writing services to running platforms.
🟡 Q29 · Tags, digests, and :latest
As they'll ask it: "What's wrong with deploying :latest?"
Model answer. It breaks the one property that makes an artifact repository a system of record: immutability. A registry is authoritative because once app:1.4.2 is pushed, that exact byte content stays behind that name-and-tag pair forever — you don't overwrite it, you publish 1.4.3. A floating tag like :latest gets re-pushed, so it no longer identifies one immutable set of bytes.
The concrete consequence is that "which image is in production" stops being answerable from the tag. Two nodes that pulled at different times can be running genuinely different code under the same tag. A rollback target becomes ambiguous. And a post-incident review can't reconstruct what was running at the time without going and checking a digest by hand. Every one of those problems shows up at exactly the moment you least want to be doing archaeology.
What I'd do instead: tag with something immutable — the git commit SHA is the usual choice because it links artifact back to source — and pin deploys either to that SHA tag or to the content-addressable digest itself. Promotion adds tags to the same digest rather than producing new bytes. Kubernetes resolving images by digest exists precisely to close this gap.
What they're really checking: whether you reason about the incident-time consequences of a build-time convenience. The rollback and forensics angles are what turn this from a rule into a reason.
Deployment Strategies — 5 questions
☺ Like you're 10: Getting the new version live is easy; getting it live without an outage and with a fast way back out is the actual job.
🟢 Q30 · Rolling, blue-green, canary
As they'll ask it: "Compare rolling, blue-green and canary deployments. When would you pick each?"
Model answer. Rolling replaces old instances with new ones incrementally, a batch at a time, against a single environment — a Kubernetes Deployment with maxUnavailable and maxSurge set, bringing up new pods, waiting for readiness, terminating an equivalent number of old ones. It's the cheapest in raw infrastructure because you never pay for double capacity. The cost shows up elsewhere: for the duration, old and new serve traffic side by side, so your API and data layer must tolerate two versions against the same schema. And rollback is slow, because undoing a rolling deployment means running another one in reverse, reintroducing the mixed-version window in the other direction.
Blue-green keeps two complete production environments. The release deploys entirely into the idle one, gets smoke-tested against production-grade infrastructure with no live traffic, and then a router — a load-balancer target-group swap, a DNS cutover, a mesh routing rule — moves 100% of traffic across in one atomic switch. Rollback is that switch run backward: seconds, not a redeploy. It costs two production-equivalent environments at least during the cutover window, and it does not limit blast radius — if a defect survived pre-cutover testing, every user hits it the instant the switch flips.
Canary sends a small percentage of real traffic — 1%, 5%, 10% — to the new version while the rest stays on the old, expanding in steps as long as monitored metrics stay within an agreed threshold, and routing back to zero if a step regresses. Argo Rollouts, Flagger, and weighted routing on most managed load balancers implement this, often with an automated analysis step that promotes or aborts based on a query rather than a person watching a dashboard.
Choosing between them is a function of blast-radius tolerance, budget, and how good your metrics are. Rolling for internal services and stateless APIs with no spare capacity budget. Blue-green where downtime itself is the risk to eliminate and doubling briefly is affordable — checkout, payments, auth. Canary where the blast radius of a bad deploy needs to be capped rather than just recovered from quickly, and where you have real-time metrics good enough to gate on.
What they're really checking: whether you can articulate the cost of each rather than reciting three definitions. The "blue-green doesn't limit blast radius" point is the one that separates a memorised answer from an understood one.
🟡 Q31 · Canary versus A/B test
As they'll ask it: "Is a canary release the same thing as an A/B test? Both send a percentage of traffic to a new version."
Model answer. They look identical in the traffic layer and answer completely different questions for different audiences.
A canary is a reliability signal: does the new build crash less, error less, and perform at least as well as the old one? Measured in infrastructure and application metrics — error rate, p99 latency, saturation — usually run by the platform or SRE side, and torn down the moment the rollout completes, because both cohorts end up on the same code. The split is a means to an end.
An A/B test is a product or business experiment: does variant B convert better, retain better, or earn more? Measured in business and behavioural metrics with statistical significance testing, run by product or growth, and deliberately kept running for a fixed sample-size window, because the split itself is the point rather than a step toward eliminating one side.
Running both under the label "canary" causes real, expensive confusion. Someone aborts a legitimate A/B test because "the canary looks worse" on a business metric it was never designed to protect. Or someone ships a reliability canary to 100% without ever checking whether it wins on the product metric a real experiment would have measured. Keeping the vocabulary separate keeps the decision rights separate too.
What they're really checking: whether you can work with product people without stepping on their experiments. This is a surprisingly practical source of friction in real teams.
🟡 Q32 · Readiness versus liveness
As they'll ask it: "What's the difference between a readiness probe and a liveness probe?"
Model answer. They answer different questions and have different consequences when they fail. A readiness probe asks "should the router send this instance traffic right now?" A failing readiness probe means the instance is simply skipped — it stays running, it just receives no requests. A liveness probe asks "is this process still functioning, or does it need to be restarted?" A failing liveness probe kills and restarts the container.
Why the distinction matters operationally: a new instance that has started but hasn't finished loading config, warming a cache, or opening a connection pool must fail readiness, so the router skips it rather than routing live requests to a process that will error on every one. Liveness catches a different failure — a process technically running but permanently wedged, deadlocked, out of file descriptors — where a restart is the correct response.
The classic misconfiguration, and the one they're usually fishing for: pointing liveness at a check that depends on a downstream dependency, such as a database. When the database has a blip, every healthy application process fails liveness and gets restarted — simultaneously, across the fleet — turning a brief dependency wobble into a self-inflicted outage, often with a restart loop that prevents recovery. Liveness should test the process itself. Readiness is the right place to reflect "I can't currently serve because a dependency is down," because it removes the instance from rotation without destroying it.
What they're really checking: hands-on Kubernetes experience. Almost nobody who has only read about probes volunteers the downstream-dependency restart loop, and almost everyone who has debugged one does.
Common wrong answer: "They're both health checks, one just runs at startup." That conflates readiness with the startup probe and misses that the consequence of failure — skipped versus restarted — is the entire distinction.
🔴 Q33 · Designing the rollback
As they'll ask it: "How do you think about rollback? What do you decide before a deploy rather than during one?"
Model answer. Rollback has to be decided before the deploy, not improvised during an incident, because during an incident you have neither the time nor the calm to design one. Three questions answered in advance:
What triggers a rollback? A human judgement call, or an automated policy tied to a specific metric threshold — say, 5xx rate above 1% sustained for two consecutive minutes. Automated is better where the metric is trustworthy, because it removes the "let's give it another five minutes" instinct that turns a two-minute incident into a twenty-minute one.
How fast can it execute? A blue-green router swap and a feature-flag flip are both seconds. A rolling deployment's reverse rollout is materially slower, and a database down-migration slower still. That number needs to be budgeted, not discovered under pressure — if your rollback takes twelve minutes, your incident has a twelve-minute floor.
Is the rollback actually safe? This is the one people miss. A schema migration that isn't backward-compatible turns "roll back the app" into "the old app now crashes against the new schema" — you've made things worse. Which is why additive, backward-compatible migrations, the expand-then-contract pattern, are the norm for any strategy that runs mixed versions even briefly. See database change management.
And I'd add: rehearse it. A rollback path that has never been executed is a hypothesis. Running it deliberately in a low-stakes window is how you find out that the old artifact was garbage-collected from the registry three weeks ago.
What they're really checking: whether you plan for failure as a first-class design activity. Candidates who only describe the happy path stand out immediately in a discipline where the failure path is the job.
🔴 Q34 · Zero downtime with a schema change
As they'll ask it: "You need to rename a column and ship the app change that uses it, with no downtime. Talk me through it."
Model answer. The constraint that drives everything: during any of rolling, blue-green with a shared database, or canary, two versions of the application code are live against one schema simultaneously. So the schema must be compatible with both the old code and the new code for the whole window — which means a rename done as a single ALTER is not available to me, because it breaks the old code the instant it lands.
The expand/contract pattern instead, in separate deploys:
Expand. Add the new column. Do not remove the old one. This migration is purely additive, so it's compatible with the currently-running code, which doesn't know the new column exists.
Dual-write. Deploy application code that writes both columns and reads the old one. Now both versions of the app remain correct, and every new row is populated in both places.
Backfill. Copy historical data into the new column, in batches sized so as not to lock the table or saturate the database. This is a background job, not a migration step, and it needs to be resumable.
Switch reads. Deploy code that reads the new column, still writing both. Verify. This is the step worth gating behind a feature flag, so switching back is a flip rather than a deploy.
Contract. Once no running code references the old column and you're past your rollback window, stop writing it, then drop it — in a later, separate deploy.
Two things I'd flag. This is five deploys, not one, and that's the honest cost of zero downtime with a stateful change. And the "drop the old column" step should wait longer than feels necessary, because it's the step that makes rollback impossible — once it's gone, going back to old code is no longer an option.
What they're really checking: whether you understand that stateful workloads are where most zero-downtime advice quietly stops applying. A candidate who works through expand/contract without prompting has almost certainly done it.
Infrastructure as Code — 5 questions
☺ Like you're 10: Writing down what the servers should look like instead of clicking buttons — and the two hard problems that creates: the tool's memory, and everyone touching it at once.
🟢 Q35 · Declarative versus imperative
As they'll ask it: "Why is nearly all infrastructure tooling declarative? What's wrong with a good shell script?"
Model answer. An imperative approach specifies the sequence of operations: create a VM, attach a disk, open port 443, install nginx. A shell script full of cloud CLI calls is imperative IaC. It works, and it only describes how to get from nothing to the desired state. It says nothing about what to do if the VM already exists, if someone changed a firewall rule manually last Tuesday, or if it's re-run against an environment that's already half-built. Correctness depends entirely on the operator running the right steps in the right order from the right starting point.
A declarative approach specifies the desired end state — there should be exactly one VM, this size, this disk, port 443 open — and delegates the how. The engine computes a diff against current reality and issues only the create/update/delete calls needed to close the gap. That's the model behind Terraform's HCL, CloudFormation's templates, and Pulumi expressing the same declarative resource graph in a general-purpose language.
The reason declarative dominates is structural rather than stylistic: infrastructure is long-lived and mutated by many actors over time, so the tool needs to reconcile current against desired state on every run rather than execute a fixed script from a known starting point. That reconciliation is also what makes plan-then-apply possible at all — you can only preview what will change if the tool can compute a diff, and a diff is only well-defined against a declared target state, not against a list of steps.
What they're really checking: whether you understand the model or just the tool. Someone who can only answer "because Terraform works that way" hasn't got the concept.
🟢 Q36 · Idempotency
As they'll ask it: "What does idempotent mean in this context, and can you write non-idempotent Terraform?"
Model answer. Idempotent means applying an operation once has the same effect as applying it many times. In IaC terms: running apply twice against unchanged configuration should produce zero changes the second time, because current state already matches desired state and the tool does nothing. That property is what makes IaC safe to re-run after a failed apply, a flaky network call, or a CI job retry — an imperative create-instance script re-run after a partial failure risks a second instance; a declarative apply re-run just finishes reconciling toward the same target.
And yes, you can absolutely break it, which is the more interesting half of the question. Idempotency isn't automatic just because a tool is declarative — it depends on the provider correctly detecting existing resources, usually by an ID kept in state, rather than blindly issuing creates. It also depends on the author: a resource definition that generates a new value on every run breaks the contract. An unpinned random suffix in a name, a timestamp baked into a tag, a data source that returns something different each call. The symptom is a config that produces a diff on every apply even though nothing meaningfully changed.
The reason that matters practically rather than aesthetically: a plan that's never clean is a plan nobody reads carefully, and idempotency is what lets applies run unattended in CI on every merge, the same way tests do. If apply weren't safe to repeat, every run would need a human deciding whether it was safe — which defeats the point of automating infrastructure changes.
What they're really checking: whether you've been on the receiving end of a perpetual diff. Naming a specific way to break idempotency is the tell.
🟡 Q37 · State and drift
As they'll ask it: "Why does Terraform need a state file at all? Couldn't it just read the cloud?"
Model answer. To compute a diff between desired and current state, the tool needs a record of what it last created and with what identifiers — that's state. It's what turns "here's a config file" into "here's exactly which real cloud resources this config file owns." Without it, the tool couldn't tell a resource it manages from an identically-shaped one created by another team, and it couldn't map a resource block in the config to a specific cloud object.
The problem that follows directly is drift: the gap that opens when real infrastructure changes without going through the tool. Someone edits a security group in the console during an incident, an autoscaler changes an instance count, another automation resizes a disk. State now disagrees with reality, and the next plan either silently reverts the manual fix — surprising and potentially disruptive, especially if that fix was mitigating something — or requires an explicit refresh or import before the plan can be trusted.
Which is why most teams enforce "changes go through the pipeline, full stop" as a hard rule rather than a suggestion, and why scheduled drift-detection runs that alert without applying are worth having. I'd also raise the operational care state needs in its own right: it contains resource identifiers and sometimes sensitive values, it lives in a remote backend rather than on a laptop, and it gets versioned so a corrupted state has something to restore from.
What they're really checking: whether you've operated IaC rather than just written it. Drift is the thing that turns a tidy repository into an unreliable one.
🟡 Q38 · State locking
As they'll ask it: "Two engineers run apply at the same time against the same state. What happens?"
Model answer. Without locking, they race. Each computes a plan against a snapshot that's already stale by the time it executes, and the outcomes range from a corrupted state file to conflicting API calls against the same resource — one apply creating something the other's plan didn't know about, or both trying to modify the same object. The damage is worse than a failed run because state corruption can leave the tool unable to reconcile at all, at which point you're doing manual imports under pressure.
Locking prevents it by serialising applies against a given state: an exclusive lock held for the duration of the operation, so a second concurrent apply either blocks or fails fast rather than racing. Implementations vary — a DynamoDB table alongside an S3 backend, a native lock in a managed backend, equivalents in other tools — but the semantics are the same.
Two related habits worth mentioning. Applies should run from CI rather than from laptops, which mostly removes the concurrency problem by construction and guarantees the applied plan matches the reviewed one. And a stale plan is the same class of bug even without a race: if someone else merges infrastructure changes between your plan and your apply, the plan you approved isn't the plan that executes, which is why saving a plan artifact and applying that exact plan is the safer pipeline shape.
What they're really checking: whether you've run IaC with more than one person, which is where all the interesting failure modes live.
🔴 Q39 · Plan review as code review
As they'll ask it: "How would you set up infrastructure changes so a team can move quickly without someone accidentally deleting the production database?"
Model answer. The core mechanism is plan-then-apply, and treating the plan as the review artifact. Plan computes the diff between config and current state and prints exactly what would be created, changed, or destroyed without touching anything; apply executes it. The separation exists so a human, or an automated policy check, can inspect before anything irreversible happens — it's the same role a pull request plays for application code.
What I'd wire up: plan runs automatically on every pull request touching infrastructure config and posts its output as a PR comment, so a reviewer sees "will destroy and recreate 1, modify 3, add 2" before approving. Apply is gated behind that approval and runs only on merge to trunk, from CI rather than a laptop, applying the saved plan so what executes is what was reviewed. State locking on, remote backend, versioned.
Then the guardrails specifically for the destructive case. Read the plan's markers, not just the resource count — a rename of a resource block, or changing an attribute the provider treats as immutable, forces a destroy-and-recreate rather than an in-place update, and that reads as a small change in a summary line. Policy-as-code checks that fail the pipeline on a destroy of anything tagged stateful, which is what compliance as code is for. Deletion protection enabled on databases at the provider level, so even an approved destroy fails. And separate state per environment so a production plan can never be produced by a change intended for staging.
The honest note: none of this survives someone applying from a laptop with admin credentials, so removing that path matters more than any single control.
What they're really checking: defence in depth. One control is a policy; four layered controls is a design, and the destroy-and-recreate trap is the detail that shows you've read a plan carefully at least once.
Configuration Management — 4 questions
☺ Like you're 10: Making the machine exist is one job; setting up what runs inside it is a different job, and mixing them up is how things get half-built.
🟢 Q40 · Where IaC stops and config management starts
As they'll ask it: "Terraform and Ansible — do you actually need both? Where's the line?"
Model answer. The conceptual boundary is precise even though tools blur it. Infrastructure as code provisions resources: it calls a cloud or virtualisation API to make a VM, a load balancer, a VPC, or a managed database exist. Configuration management configures software on a resource that already exists: installing packages, templating config files, managing users and permissions, ensuring services run in the desired state. Terraform asking a cloud for an instance is provisioning; Ansible then connecting to that instance to install nginx, template its config, and start the service is configuration management.
The practical test that holds up: if the answer to "does this resource exist yet" changes, it's IaC. If the resource already exists and you're changing what's running on it, it's configuration management.
It genuinely gets fuzzy in two places, and I'd name them rather than pretend the line is clean. Cloud-init and user-data scripts run at boot and can do light configuration, so simple VM fleets sometimes skip a dedicated config layer entirely. And the tools overlap — Ansible ships modules that provision cloud resources, and Terraform's provisioner blocks can run remote commands, though Terraform's own documentation calls provisioners a last resort, precisely because reaching across the boundary breaks the separation both tools are built around.
Worth adding: in a container-first estate this boundary moves rather than disappears. What used to be config management largely becomes the image build, and the remaining "configure a running machine" surface shrinks to the nodes themselves — which is the argument for immutable infrastructure.
What they're really checking: whether you'd put the right change in the right layer, because teams that get this wrong end up with two tools both half-owning the same resource.
🟡 Q41 · Push versus pull
As they'll ask it: "Ansible versus Puppet — what's the actual architectural difference and when does it matter?"
Model answer. It's push versus pull, and the trade-offs follow directly from the shape.
Push, with Ansible as the reference: a control node connects outward to each managed host, typically over SSH, and executes instructions there on demand. No persistent agent on the hosts — it needs Python present and a credential the controller can use. A run happens when a human or a CI job triggers it, and nothing happens on the fleet in between. That's simple to reason about, because state changes only when you deliberately change it, and easy to bootstrap, because there's nothing to install on a thousand fresh hosts first. The cost is that push doesn't self-heal: someone hand-edits a config at 2 a.m. and that host silently drifts until the next run. Fleet-wide changes also fan out from one controller, which becomes a bottleneck and a blast-radius concern at scale unless you tune parallelism and batch the rollout.
Pull, with Puppet or Chef: each host runs a persistent agent that periodically — Puppet's default agent run interval is 30 minutes — contacts a central server, pulls its assigned desired state, and reconciles locally without waiting to be told. That buys continuous self-healing: a manually edited file gets reverted, a stopped service restarted, automatically. It scales horizontally almost for free, since each host does its own work. The cost is real operational overhead — an agent to install and keep alive everywhere, a central server that's now its own infrastructure to run and secure, certificate trust between them — and less precise timing, since "eventually, within the interval" is the default guarantee.
The honest summary is that it's a trade of control for resilience. Push gives you a single moment when change happens, decided by a human, easy to gate behind a pipeline. Pull gives up that precision for drift correction you don't have to remember to run. Plenty of shops run both: push through CI for planned rollouts, pull on fleets where unauthorised drift is the bigger risk.
What they're really checking: whether you can compare architectures rather than products. Anyone who answers "Ansible is easier" hasn't engaged with the question.
🟢 Q42 · Why playbooks aren't scripts
As they'll ask it: "What makes an Ansible playbook different from a bash script that does the same thing?"
Model answer. Idempotency, and it comes from describing state rather than actions. A bash script running useradd deploy fails the second time, because it describes an action with no awareness of current state. A config management task saying "ensure user deploy exists" describes a desired end state — the tool checks first and acts only if there's a gap. That's why these tools are called declarative even though the file looks like a list of steps.
You can see it in the module names: state: present, not "install." Re-running the playbook against a host that already matches produces "ok" on every task rather than an error or a duplicated line in a config file. That property is what makes it safe to run the same playbook on a schedule, safe to re-run after a partial failure, and safe to run against a mixed fleet where some hosts are already configured and some aren't.
The caveat worth adding, because interviewers like it: idempotency is a property of the modules, not of the file format. The moment you drop to a raw shell or command task without a guard, you've reintroduced a script inside a playbook and lost the guarantee for that task. Which is why those tasks want a creates or a conditional, and why a playbook full of shell tasks is a smell rather than a style.
What they're really checking: whether "declarative" is a word you use or a property you can test for. The shell-task caveat is what shows the latter.
🔴 Q43 · Fighting drift
As they'll ask it: "You inherit a fleet of a few hundred VMs, configured by hand over several years. How do you get to a managed state?"
Model answer. I'd resist the instinct to write one playbook and run it fleet-wide, because against hand-built hosts that's how you take a service down at scale. The order I'd work in:
Measure the drift before correcting it. Run in check or dry-run mode against a representative sample to find out how far reality is from any coherent baseline. What you usually discover is that the fleet isn't one fleet — it's four generations of build, and treating them as one is the actual risk.
Codify what exists, not what you wish existed. The first playbook should describe the current working configuration, so applying it is a no-op. That gets you a reviewed, versioned description of the fleet before you change anything, and it's the artifact that makes every later change reviewable.
Roll out in batches with a canary group. Small serial batches, health-checked between them, so a bad task hits five hosts rather than three hundred.
Then close the door. Drift keeps returning unless the manual path is removed — SSH access restricted, changes going through the pipeline, and either a pull agent or a scheduled check-mode run that alerts on divergence without applying. The alerting version is the one I'd start with, because auto-correcting drift on a fleet you don't yet understand can revert a manual fix that's holding something together.
The strategic answer I'd offer alongside it: for the long term, the more durable fix is to stop configuring long-lived machines at all. Bake a golden image, deploy new instances from it, and replace rather than repair — immutable infrastructure makes drift structurally impossible instead of continuously corrected. That's a bigger programme than a config-management rollout, so I'd frame it as the destination rather than the first step.
What they're really checking: whether you can sequence a migration against a live estate without a big-bang change. "Codify what exists first" is the answer that signals you've done one.
Containers & Orchestration — 5 questions
☺ Like you're 10: Why a container starts in a blink when a virtual machine takes a minute, and what an orchestrator is actually for.
🟢 Q44 · Containers versus VMs
As they'll ask it: "What's the actual difference between a container and a VM?"
Model answer. A virtual machine gets its isolation from a hypervisor that virtualises hardware — CPU, memory, disk, network interfaces — and boots a complete guest operating system, kernel included, on top of it. That guest kernel takes real time to initialise, tens of seconds typically, and consumes real memory and disk just to exist. Ten VMs on a host means ten kernels.
A container gets its isolation from the host kernel itself, using two Linux primitives: namespaces, which give separate views of process IDs, network interfaces, mounts, hostname and IPC so a container can't see outside itself, and cgroups, which put hard limits on CPU and memory so one container can't starve its neighbours. No second kernel boots. A container is a process, or a small group of processes, launched by a runtime such as containerd — or the lower-level runc implementing the OCI runtime spec — with those namespaces and cgroups applied. Starting one is closer to fork-and-exec than to booting a machine, which is why start times are milliseconds and why a host runs hundreds of containers where it would run a dozen VMs.
The part I'd make sure to say, because it's the part marketing omits: the isolation is real but weaker than a VM's. Every container on a host shares one kernel, so a kernel vulnerability or a kernel panic has a blast radius of "everything on this host," not "one VM." That's the actual trade — density and startup speed against a thinner isolation boundary — rather than containers simply being VMs done better.
What they're really checking: whether you know the mechanism (namespaces and cgroups) or only the analogy. Naming both primitives is the difference.
🟡 Q45 · Image layers and cache ordering
As they'll ask it: "Our image builds take four minutes even for a one-line code change. Any idea why?"
Model answer. Almost certainly Dockerfile instruction ordering invalidating the layer cache. An image is a stack of read-only layers, each a filesystem diff from the one below, combined at runtime by a union filesystem. Layers are content-addressed and cached — but any instruction that changes invalidates the cache for every layer below it.
The classic mistake is copying the whole source tree and then installing dependencies. Because the source changes on every commit, the COPY layer is invalidated every time, so the dependency install below it re-runs from scratch on every build. The fix is to copy only the dependency manifest first, run the install, and copy the rest of the source afterwards — so editing application code invalidates only the last layers, and a cached dependency install is reused. That's typically the difference between a four-minute build and a ten-second one.
Other things I'd check on the same pass: whether the CI runner has a warm layer cache at all, since ephemeral runners start cold unless you configure a registry-backed cache; whether a multi-stage build could keep build tooling out of the final image, which shrinks both the push and the attack surface; and whether the base image is pinned by digest rather than a floating tag, because a base that changes underneath you invalidates everything and quietly breaks reproducibility.
What they're really checking: practical Docker experience. This is a very common real problem, and knowing the fix by reflex is a strong signal.
🟢 Q46 · Pod, Deployment, Service
As they'll ask it: "Explain what a Pod, a Deployment and a Service each do and how they relate."
Model answer. A Pod is the smallest deployable unit — not a container itself, but a wrapper around one or more containers that share a network namespace, so one IP address, and can share storage volumes. Most Pods run exactly one application container; a second container in the same Pod is the sidecar pattern, a helper co-located and co-scheduled with the main one, commonly used for log shipping or a service-mesh proxy that intercepts the main container's traffic. Pods are deliberately disposable: Kubernetes expects to destroy and recreate them rather than keep any individual one alive.
A Deployment manages a set of identical Pod replicas and their rollouts. It's what implements self-healing — replacing a Pod that dies — and horizontal scaling, by changing the replica count, and it drives rolling updates when the image reference changes.
A Service gives a stable network identity to a set of Pods, selected by label rather than by tracking individual IPs. Since Pods come and go and get new IPs on every reschedule, the Service is what gives everything else in the cluster one unchanging address and DNS name to talk to.
The way I'd tie it together: the Deployment answers "how many and which version," the Pod answers "what actually runs," and the Service answers "how does anything find it." Remove any one and the model breaks — without the Service, callers would have to track ephemeral IPs; without the Deployment, nothing replaces a dead Pod.
What they're really checking: baseline Kubernetes fluency. It's a warm-up, but a hesitant answer here changes how hard the rest of the round gets.
🟡 Q47 · Why an orchestrator at all
As they'll ask it: "We run about a dozen containers on three VMs with Compose and a load balancer. Do we need Kubernetes?"
Model answer. Honestly, maybe not, and I'd want to know what's actually hurting before recommending it. Kubernetes solves a specific set of problems that appear past a certain scale: scheduling containers onto hosts with capacity, restarting what dies, service discovery when IPs change constantly, rolling out new versions without downtime, and scaling replicas up and down against load. If none of those are currently painful, adopting it means taking on a substantial operational surface — a control plane to run or pay for, networking and storage abstractions to learn, RBAC, upgrades — in exchange for solving problems you don't have yet.
What would change my answer: the number of services growing past what a person can place by hand; needing per-service scaling rather than scaling the whole VM; a deployment strategy that requires health-gated progressive rollout; multiple teams needing isolation on shared infrastructure; or an on-call burden dominated by "a process died and nobody noticed." Those are the symptoms an orchestrator genuinely fixes.
The middle ground worth raising is that managed container services from the cloud providers cover a good part of that gap with much less operational surface, and "boring technology" is a legitimate argument — the right answer is often the least powerful tool that solves the actual problem, because every tool you adopt is a tool someone has to be on call for.
What they're really checking: whether you'd introduce complexity by default. Saying "you probably don't need it yet, here's what would change my mind" is usually the stronger answer.
🔴 Q48 · The thinner isolation boundary
As they'll ask it: "You're running workloads from several teams on one cluster. What worries you?"
Model answer. The starting point is that containers share the host kernel, so the isolation boundary between two containers on a node is thinner than between two VMs. That's a design trade, not a defect, but it sets the threat model: a kernel-level vulnerability or an escape is a blast radius of everything on that host, and in a shared cluster "everything on that host" now includes another team's workload.
What I'd want in place, roughly in order of value. Resource limits on every workload, so one team's runaway process can't starve the node — requests and limits set, and enforced by policy rather than left to whoever wrote the manifest. Namespace separation with RBAC, so a team can't read another team's secrets. Network policy, because by default cluster networking is usually flat and any pod can reach any other. Containers running as non-root with dropped capabilities and a read-only root filesystem where possible, which removes most of the easy escalation paths. Admission policy rejecting privileged containers and host mounts outright. And image provenance — only images from a trusted registry, scanned, ideally signature-verified, since a compromised base image bypasses every runtime control.
Where the isolation requirement is genuinely hard — untrusted third-party code, or strict regulatory separation — I'd say plainly that node-level or cluster-level separation is the honest answer rather than trying to make shared-kernel isolation carry more weight than it can. Separate node pools per tenant, or separate clusters, cost more and are a much simpler thing to reason about in an audit.
What they're really checking: security maturity, and whether you'll admit the limit of a control rather than layering more controls onto a boundary that was never designed for that job.
Monitoring & Observability — 5 questions
☺ Like you're 10: Watching for the problems you already predicted, versus being able to answer a brand-new question at 3 a.m. — and why alerts that cry wolf are worse than no alerts.
🟢 Q49 · Monitoring versus observability
As they'll ask it: "Is 'observability' just a new word for monitoring?"
Model answer. No, though they're complementary rather than competing and most production systems run both.
Monitoring is collecting a predetermined set of signals and alerting when they cross a predetermined threshold. Someone decides in advance which failure modes matter — CPU above 90%, disk above 85%, 5xx rate above 1% — and builds a dashboard and an alert for each. Its structural limit is that it can only tell you about questions it was built to ask. If a new failure mode appears — a subtle interaction between a cache eviction policy and a downstream retry storm — monitoring stays green while the system is degraded, because green was defined as "none of the metrics we thought to collect have crossed their threshold," not "the system is healthy."
Observability is a property borrowed from control theory: how well a system's internal state can be inferred from its external outputs. Applied to software, it means collecting telemetry raw and high-cardinality enough — not pre-aggregated into fixed dashboard panels — that an engineer can ask a novel question during an incident and get an answer without having predicted that question in advance. "Show me every request from customer 4471 that touched checkout and took over 800ms in the last hour, broken down by pod" is an observability query, and it requires the underlying events to carry those dimensions as separate queryable fields.
The test I'd offer for telling them apart in practice: if answering a new question about production requires shipping code to add a metric or a log line, you have monitoring but not observability for that question. If you can answer it by querying data you were already collecting, you have observability.
What they're really checking: whether you can define observability without the marketing. High cardinality is the technical substance and it's the word most candidates leave out.
🟢 Q50 · The three pillars
As they'll ask it: "Metrics, logs and traces — when do you reach for each?"
Model answer. Each answers a different question with a different cost profile.
Metrics are numeric time series — a value, a timestamp, a set of labels. Cheap to store and query because they're pre-aggregated by design, which makes them excellent for dashboards and threshold alerts and poor for root-causing a single anomalous request. A metric tells you error rate went from 0.1% to 4%; it can't tell you which requests failed or why.
Logs are discrete timestamped events, typically a line per occurrence. Structured logs — consistent fields rather than free text — are what make them queryable at useful granularity. Richest single-event detail, most expensive pillar to store and search at volume, since every request can generate several lines.
Traces follow one request's path across every service it touches, as a tree of timed spans linked by a trace ID propagated through headers. A trace answers "where did the 800ms go" directly: 40ms in the gateway, 600ms waiting on recommendations, 160ms writing to the database. OpenTelemetry has become the standard vendor-neutral instrumentation layer for producing them.
The way they combine is what actually matters: a typical incident moves through all three. A metric-based alert fires. A trace narrows it to one service and one span. A log line from that service at that timestamp shows the actual exception. No single pillar is sufficient — metrics tell you something is wrong and roughly how much, traces tell you where, logs tell you what exactly.
What they're really checking: whether you'd design telemetry deliberately or just turn everything on. The cost differences are what force the design.
🟡 Q51 · The four golden signals
As they'll ask it: "New service, nothing instrumented, you have an afternoon. What do you add?"
Model answer. The four golden signals from Google's SRE book, because they're deliberately generic — the same four apply to a REST API, a queue consumer, or a batch job — which makes them the right default when you don't yet know the service's specific failure modes.
Latency — how long requests take, reported as a distribution (p50, p95, p99), never a single average. An average of 120ms can hide a p99 of four seconds affecting one user in a hundred, and that tail is usually where the real problem lives. Worth splitting successful from failed requests too, since a fast error and a slow error mean different things.
Traffic — demand, in whatever unit fits: requests per second, messages consumed per second. Traffic is the denominator that makes the other three interpretable — fifty errors a second means something very different at 100 req/s than at 100,000.
Errors — the rate of requests that failed, whether by explicit failure code, implicit failure (a 200 with wrong content), or policy violation (slower than an agreed budget). What counts as an error should match what callers care about, not what's easiest to count.
Saturation — how full the service is relative to its limit: CPU and memory, but also queue depth, connection pool usage, thread pool occupancy. It's the leading indicator — a service at 92% memory isn't failing yet, but it predicts the other three are about to get worse.
With an afternoon I'd instrument those four, put them on one dashboard, and page on symptoms only. Everything more bespoke comes after there's a baseline to compare against.
What they're really checking: whether you have a default that works without knowing the system. The "never a single average" point is the detail that shows you've debugged a latency tail.
🟡 Q52 · What makes an alert good
As they'll ask it: "What are your rules for what should page someone?"
Model answer. Three principles, and they're all about preserving trust in the pager.
Every alert must be actionable. If someone gets paged and there's nothing to do except acknowledge and go back to sleep, the alert shouldn't exist — fix the underlying condition, downgrade it to a dashboard, or delete it. An alert with no corresponding action trains the on-call to skim and dismiss, which is exactly the reflex that causes a real page to be missed later.
Page on symptoms, not causes. Page when users are actually affected — elevated latency, elevated error rate, a golden signal breached — not on every internal condition that might eventually cause that. "Database CPU at 85%" is a cause that may never become a symptom; "p99 above two seconds for five minutes" is a symptom that always means someone is having a bad time now. Causes belong on dashboards for investigation after a symptom-based page has already woken someone. Otherwise every dependency gets its own alert and one real incident pages the same engineer a dozen times.
Set thresholds to avoid fatigue. A threshold set too sensitively fires on routine noise — a brief traffic spike, one slow request during a deploy — and trains responders to distrust pages, which is the single biggest predictor of a missed real incident.
I'd add one practical rule: every page should have a runbook link, even a thin one. Not because the runbook will cover the incident, but because the act of writing it forces you to answer "what would someone actually do about this," which is the actionability test made concrete.
What they're really checking: whether you've carried a pager. The symptoms-not-causes principle is easy to state and only obviously important to someone who has been paged six times for one root cause.
🔴 Q53 · The team drowning in alerts
As they'll ask it: "The on-call rotation gets around forty pages a week and most are noise. Where do you start?"
Model answer. I'd start by making the problem visible rather than by deleting alerts, because deleting the wrong one is how you get an outage that becomes an argument against the whole effort.
Get the data. Export a few months of pages and group by alert rule. It's almost always heavily skewed — a handful of rules generate most of the volume. Then classify each page: did it require action, did it self-resolve, was it a duplicate of another page for the same root cause?
Kill the non-actionable ones outright. Anything that self-resolved every time it fired, or where the on-call's only action was to acknowledge it, goes to a dashboard. This is usually a large fraction of the volume and it's uncontroversial once the data is on the table.
Collapse the duplicates. A single incident paging six times means you're paging on causes. Move those to symptom-based alerts at the user-facing boundary and demote the causes to context that's available when you investigate.
Fix the thresholds that fire on blips. Multi-window, multi-burn-rate alerting is the standard technique — comparing a short window against a longer one, requiring both to breach before paging — so sustained degradation pages and brief self-resolving spikes don't. That's the mechanism behind SLO-based alerting more generally; see SLOs, error budgets and toil.
Then make it stick. Review page volume in the on-call handover every week, and treat any alert that fires without action as a bug with an owner. Otherwise the noise regrows within two quarters.
The framing I'd use with the team: forty pages a week isn't an alerting problem, it's a reliability problem plus an alerting problem, and the alert cleanup is what makes the reliability work visible.
What they're really checking: whether you'd approach a cultural problem with data. Also whether you know multi-window burn-rate alerting, which is the specific technical answer to "how do I stop paging on blips."
Incident Management — 4 questions
☺ Like you're 10: Something will break; what decides whether it's a five-minute blip or a four-hour outage is almost never the fix itself.
🟢 Q54 · Severity scales
As they'll ask it: "Why bother with severity levels? Isn't it obvious how bad something is?"
Model answer. It's obvious in hindsight and contested at 3 a.m., which is exactly when you need it settled. Severity is the single input that decides staffing, response-time expectation, and communication cadence all at once, so it has to be agreed before the incident rather than argued during it.
A typical four-tier scale: SEV1 — complete outage or a security breach affecting all or nearly all users; everyone relevant paged immediately, an incident commander assigned within minutes, and a status page update before root cause is even known. SEV2 — significant degradation; a major feature down or a meaningful subset of users unable to complete a core workflow; primary on-call paged, response expected in roughly fifteen minutes. SEV3 — a real bug with a workaround or a narrow blast radius; into the queue, next business day, no page. SEV4 — cosmetic or negligible; backlog.
Getting classification wrong misfires in both directions, and both are costly. Over-classifying burns out the rotation with 3 a.m. pages for a footer typo, which is how people learn to under-classify next time. Under-classifying leaves a genuine outage running for hours before anyone with the authority to fix it knows. I'd also say the exact tier definitions matter far less than that they're written down and shared — a team that agrees "SEV2 means a subset of users can't check out" resolves the argument in ten seconds.
What they're really checking: whether you've worked inside a real incident process or improvised one each time.
🟡 Q55 · The incident commander
As they'll ask it: "What does an incident commander do, and who should it be?"
Model answer. The IC's job is coordination, decisions and communication — explicitly not hands-on-keyboard debugging. They decide what gets tried next when two fixes are on the table, decide when to pull in another team, decide when to declare the incident mitigated versus resolved, and own the outward narrative. The engineers with the deepest context stay heads-down on the fix; the IC keeps everyone else pointed at one consistent picture of reality instead of several conflicting ones.
A single point of coordination speeds resolution for a concrete reason: without it, incidents regress into duplicated or conflicting effort — two people independently restarting the same service, one rolling back a deploy while another is mid-way through a different mitigation, both burning time re-establishing what the other already tried. The IC is also the one person with standing to make a call under uncertainty — "we're rolling back now, we'll chase root cause after" — and have it stick, rather than the team stalling on consensus while the outage runs. On larger incidents a separate scribe keeps the timeline, freeing the IC to focus on decisions.
Who it should be: whoever can hold the picture and is not needed on the keyboard. Explicitly not necessarily the most senior engineer — which is the failure mode I'd name, because it's the common one. The badge lands on the most senior person present, who immediately starts debugging because that's what they're good at, and now nobody is tracking the timeline, nobody is answering stakeholders, and two responders are quietly duplicating each other. The IC doesn't need to be the strongest engineer in the room. They need to be the one person deliberately not staring at a terminal.
What they're really checking: whether you've been in a badly-run incident and can name why it went badly. The "most senior person starts debugging" failure is the giveaway that you have.
🟡 Q56 · Mitigate before you resolve
As they'll ask it: "Walk me through what happens from the moment an alert fires."
Model answer. Five stages. Detect — an alert fires, ideally from automated monitoring rather than a customer support ticket, because "a customer told us" is itself a finding. Triage and acknowledge — the on-call acks and assigns a severity, which starts the response clock. Mitigate — the fastest available action that stops user impact: a rollback, a feature flag flipped off, traffic failed over to a healthy region. Resolve — the underlying issue actually fixed and the service confirmed healthy rather than just no longer visibly broken. Review — a blameless post-incident review once the dust settles, reconstructing the timeline and producing concrete follow-up actions.
The distinction I'd emphasise is mitigation versus resolution, because it's where teams lose the most time. Mitigation deliberately is not a full fix — it buys time and stops the bleeding, usually before root cause is known. The instinct to understand before acting is a good engineering instinct and a bad incident instinct: if a rollback stops the impact, roll back first and diagnose against a system that isn't currently hurting anyone.
That's also why most teams track mean time to mitigate alongside mean time to restore. From a user's perspective the incident effectively ends at mitigation. Full resolution and the review that follows matter enormously for long-term reliability, but by the time either happens the user-facing impact has already stopped.
What they're really checking: whether your instinct under pressure is to stop the bleeding or to satisfy your curiosity. Say "roll back first, diagnose after" out loud — it's the answer they want to hear.
🟡 Q57 · Communicating during an incident
As they'll ask it: "Who do you tell what, and how often, while an incident is running?"
Model answer. Two audiences needing different things. External communication runs through a public status page: short, factual, stating what's degraded, roughly since when, and that it's being worked on, updated as the picture changes. Internal runs through a dedicated channel or bridge, so support, sales and leadership can see current impact and expected timeline without pulling a responder out of the incident to ask.
Cadence is set by severity, not by how much has changed. A SEV1 typically gets an update every fifteen to thirty minutes even when the honest content is "still investigating, no change" — silence during an active outage reads as either abandonment or a bigger problem than it is, and people fill an information vacuum with worse guesses than the truth would give them. Lower severities update less often, or only at resolution.
A good update states three things and nothing else: what is known, what is being done, and when the next update lands. Not speculation about root cause before it's confirmed — a retracted cause is worse than no cause, because customers quote the first version back at you for months. And the IC owns the cadence, or delegates it to the scribe, precisely so the engineers debugging are never interrupted to answer "any update?" in six channels at once.
What they're really checking: whether you understand that incident communication is a job someone has to be doing, not something that happens when a responder has a spare minute.
DevOps Toolchain — 3 questions
☺ Like you're 10: Work out what job needs doing before arguing about which brand does it best.
🟢 Q58 · Categories, not vendors
As they'll ask it: "Describe the toolchain you'd expect a team to have."
Model answer. I'd answer in categories rather than products, because the category tells you what problem class is being solved regardless of brand. Roughly eight, and they form a chain rather than a list: source control holds the change; a CI/CD orchestrator picks it up and drives the pipeline; infrastructure as code and configuration management make sure the target environment exists and is configured before anything lands on it; the build packages the result and pushes it to an artifact registry; containers and orchestration schedule that image onto running infrastructure; monitoring and observability watch what happens once it's live; and incident and on-call tooling routes the alert to a human and coordinates the fix.
Naming them that way is useful in a real conversation because it turns "do we have a gap?" into an answerable question. A team with no artifact registry is rebuilding per environment whether they realise it or not. A team with three overlapping CI tools has a redundancy, not a strategy. And a team with excellent observability and no incident tooling can see the problem but can't reliably get a human to it.
What they're really checking: whether you can reason about a stack you've never seen. Vendor-first answers don't transfer between companies; category-first answers do.
🟡 Q59 · How you'd actually choose
As they'll ask it: "How would you pick between two tools that both do the job?"
Model answer. Two questions in sequence, and the order matters. First, which stage of the lifecycle needs support — the category decision. Only then, which product fits the team's constraints. Collapsing those two is how teams end up either missing a stage entirely or running three tools that all do the same job slightly differently.
On the product decision, the criteria I'd actually weigh: does it integrate with what we already run, since integration cost usually dwarfs licence cost; hosting model, because self-hosted means someone is on call for it; what in-house expertise already exists, since a slightly worse tool the team knows often beats a better one nobody does; the exit cost, because the question isn't just how good it is but how hard it is to leave; and total cost including the engineering time to operate it, not just the invoice.
I'd invoke "choose boring technology" explicitly. Every novel tool spends some of a finite budget for novelty, and that budget is better spent on whatever is actually differentiating about the product. A four-person team and a hundred-engineer organisation both need a CI system; buying the hundred-engineer one for the four-person team clutters a space with nowhere to put it. The strongest version of this answer names a time you argued against adopting something you personally found interesting.
What they're really checking: whether you'll bring a tool preference and try to install it, or assess what's there first. Hiring managers have been burned by the former.
🔴 Q60 · The inherited sprawl
As they'll ask it: "You join and find three CI systems, two monitoring stacks and both Terraform and CloudFormation in use. What do you do?"
Model answer. Not consolidate immediately, which is the instinct and usually the wrong first move. Sprawl like that is normally the fossil record of acquisitions, reorganisations, or a team that adopted something and then the person who championed it left. Until I know which, I can't tell which of the three CI systems is the one holding up something critical.
Map before moving. Which services actually deploy through which system, who owns each, when each was last touched. It's common to find one of them handles two dormant services and could be retired next month, and another one is doing something nobody documented — a nightly job everything depends on.
Rank by pain, not by tidiness. Two monitoring stacks is worse than two CI systems, because during an incident the responder has to know which one has the signal, and that costs minutes at the worst possible moment. Two IaC tools is annoying but survivable if they own disjoint resources; it becomes urgent if they both touch the same ones, because now neither state file is trustworthy.
Stop the growth first. Pick the target for each category and make it the default for anything new. That's cheap, uncontroversial, and it stops the problem compounding while the migration is planned.
Then migrate the highest-pain one, with an owner and a deadline. A consolidation without a named owner and a date is a wiki page, not a plan. And retire the old one properly — a decommissioned system still running is the worst of both worlds, because it still needs patching and nobody is watching it.
The thing I'd resist is a big-bang standardisation programme across all three categories at once. It competes with product work, it takes longer than promised, and if it stalls halfway you've added a fourth tool to the collection.
What they're really checking: judgement and political realism. Enthusiasm for a rewrite is a yellow flag; sequencing by operational pain is the senior answer.
Scenario & design questions
☺ Like you're 10: The big open questions with no single right answer — where they're watching how you think, not what you already know.
These rounds are deliberately underspecified, and the most common way to fail one is to start designing immediately. There is no canned answer to memorise here, so what follows is a structure plus six worked examples of how to apply it. Use the structure out loud — narrating "let me get the constraints first" is itself part of what's being assessed.
- Clarify the actual problem. Two or three questions, no more, before you touch the design. What's the current pain — is it speed, is it failure rate, is it that nobody trusts the process? Who's affected? What's already been tried and why did it not work? A candidate who asks "what does 'slow' mean here — minutes, hours, or days?" has already outperformed one who starts drawing.
- Surface the constraints. Team size and skills. Cloud or on-prem, and which. Regulatory requirements. Budget for infrastructure and for engineering time. Whether there's an existing platform team. Whether the thing is stateful. Constraints are what make one design better than another, and asking for them is not stalling.
- Design the happy path. End to end, at moderate depth, naming categories rather than products unless they've told you the stack. Say what each piece is for as you place it.
- Design the failure path. This is the part most candidates skip and the part interviewers weight most heavily. What breaks? How do you know it broke? How fast can you undo it? What happens if the undo also fails?
- Name the trade-off you made, and what you'd measure. Close by saying what your design is bad at, and which numbers would tell you within a month whether it worked. That closing move is what turns a design into an engineering judgement.
Scenario 1 · Design a delivery pipeline for a growing team
As they'll ask it: "Thirty engineers, one large application, currently deploying about once a fortnight in an evening window. Design what good looks like in a year."
How to approach it. Clarify first: is the fortnightly cadence a technical limit or a policy? Is there a change advisory board? Is the application deployable in pieces or only whole? Is there a test suite anyone trusts? Those four answers change the design more than anything about tooling.
The happy path I'd sketch: pipeline-as-code in the application repository; stages ordered cheapest-first — lint, unit, build, integration, scan, package, deploy-staging, smoke, deploy-prod; one artifact built once and promoted by tag; trunk-based branching with branches measured in hours; feature flags so incomplete work can merge; and a deployment strategy matched to the service's blast-radius tolerance.
The failure path: what does a failed stage do — stop the pipeline and notify the author, no soft failures; what does a bad production deploy do — an automated rollback trigger tied to a metric threshold, with a rehearsed manual path behind it; what does a failed rollback do — flags as the faster undo, and a known-good artifact still present in the registry.
The trade-off and the measurement: this is a year of work, most of it cultural rather than technical, and the hardest part is not the pipeline — it's getting a test suite people trust enough to remove the evening window. I'd measure it with the four DORA metrics on a rolling ninety-day window, and I'd expect lead time to move first and change failure rate to get temporarily worse before it gets better, because more frequent deploys surface problems the fortnightly batch was hiding.
Scenario 2 · A deploy nobody wants to do
As they'll ask it: "Our releases happen on Saturday mornings, take four hours, and need six people on a call. Fix it."
How to approach it. The question behind the question is why it takes four hours and six people, and that's genuinely worth asking rather than assuming. Common causes: manual steps in a runbook, a database migration that has to be sequenced by hand, several services that must go in a specific order, a smoke test that's actually a person clicking through the application, or a rollback plan so slow that everyone wants a big window in case they need it.
The approach I'd narrate: instrument the existing release first. Time each step across two or three releases and find where the four hours actually go — it's usually one or two steps, not evenly spread. Then automate the biggest manual step, keeping the Saturday window while trust is built. Shrink the batch: the reason a release needs six people is usually that a fortnight of changes is going out at once, so nobody can predict what breaks. And decouple the services if the ordering requirement is real, because "A must go before B" is a coupling problem wearing a deployment costume.
The failure path and the honest trade-off: the risk of this programme is doing it in the wrong order — automating the release before shrinking the batch just gets you a faster four-hour release. And I'd be explicit that Saturday morning is often a symptom of a rollback that's too slow, so investing in rollback speed can be what earns the move to a weekday.
Scenario 3 · Observability from scratch
As they'll ask it: "New service going live next month. Nothing is instrumented. What do you put in and what do you page on?"
How to approach it. Clarify what the service does and who depends on it, because "what counts as an error" is a product question rather than a technical one — a queue consumer that drops a message and a checkout API that returns 500 have very different definitions of failure.
Then a defensible default: the four golden signals instrumented as metrics, latency as a distribution rather than an average; structured logs with a request ID from day one, because retrofitting correlation IDs is far more painful than adding them; trace context propagated at the edges even if you don't have a trace backend yet, since the instrumentation is the expensive part and the backend can come later. One dashboard with the four signals visible without scrolling.
On alerting: page on symptoms only — error rate and latency at the user-facing boundary — and put the causes on the dashboard. Two or three pages maximum at launch, because a new service with fifteen alert rules is a new service that nobody trusts by week three. Add rules as you learn the actual failure modes, which is what the first month of running it is for.
The trade-off to name: high-cardinality telemetry is what makes novel questions answerable and it's also what makes the bill grow, so sampling strategy and retention are decisions to make deliberately at the start rather than discover in a finance review.
Scenario 4 · Secrets in the pipeline
As they'll ask it: "You find production database credentials pasted into the CI configuration as plain environment variables. Walk me through what you do."
How to approach it. Treat it as an incident first and a design problem second, and say so — the order matters. Anything that has been in a CI config has been in logs, in build output, on runner disks, and in the repository history if it was committed. So: rotate the credentials, don't just move them. Then check the blast radius — where else does this credential appear, what did it have access to, is there any evidence of use you can't account for. Then scan history properly, since removing a secret from the current file leaves it in every clone of the repository.
The design fix afterwards: a dedicated secrets manager rather than encrypted config, with the pipeline fetching at run time rather than holding a copy; short-lived credentials over long-lived ones wherever the platform supports it, because a credential that expires in an hour is a much smaller problem when it leaks; scoping so the pipeline's credential can do exactly what the pipeline needs and nothing else; secret scanning in pre-commit and in CI so the next one is caught before it merges; and ephemeral runners so nothing persists on disk between jobs. Secrets & credential management covers the rotation mechanics that make this survivable.
The judgement note worth adding: I'd also ask why it was done that way before proposing the fix. It's usually not carelessness — it's that the proper path was too slow or too undocumented, and if I don't fix that, the workaround comes back under a different name.
Scenario 5 · Structuring infrastructure across environments
As they'll ask it: "How would you structure infrastructure code for dev, staging and production?"
How to approach it. The two properties I'd design for: staging should differ from production only in ways you can enumerate, and a change intended for staging must be structurally incapable of hitting production.
That points to separate state per environment, always — one state file spanning environments means a mistake in a shared module can plan a change in production while you're working on dev. Shared modules for the resource shapes, with environment-specific values as inputs, so the difference between environments is a variables file you can read in one screen rather than three diverged copies of the same code. Separate credentials per environment so the dev pipeline cannot authenticate to production at all, which is a stronger control than any policy.
Then the honest part, which is where the interesting discussion usually goes: environments are never actually identical, because production has data volume, real traffic, and third-party integrations that staging doesn't. So I'd rather have a small, cheap staging that's structurally identical and explicitly smaller — and be clear about which classes of bug it therefore cannot catch — than an expensive staging that pretends to be production and quietly isn't. Load-related and data-shape bugs need progressive delivery in production to catch, not a bigger staging.
Scenario 6 · The migration under a deadline
As they'll ask it: "You need to move forty services to a new deployment platform, and the old one's contract ends in six months. How do you plan it?"
How to approach it. A hard external deadline changes the shape of the answer, and naming that explicitly is part of the answer. There's no option to descope the destination, so the flexibility has to come from somewhere else: sequencing, scope per service, or how much modernisation rides along.
How I'd sequence: inventory first, classified by risk and by how much each service actually uses of the old platform's features — there will be a long tail of simple services and a handful of hard ones. Migrate two or three simple services end to end first, not to make progress but to find out what the migration actually costs and to build the paved path. Then run the tail in parallel using that path, and save the hard ones for when the path is proven, with a decision point early enough that "this one needs a different plan" is still an option.
The failure path: what happens if a migrated service misbehaves — can it go back to the old platform, and for how long is that true? Dual-running for a period costs money and is usually worth it. And I'd want a written point of no return per service, so nobody is guessing during an incident whether rollback is still available.
The trade-off to name out loud: the temptation on a migration like this is to fix everything else at the same time, since you're touching every service anyway. I'd resist it — a migration that also becomes a re-architecture is how a six-month deadline becomes a nine-month one. Migrate first, improve after, and keep a list of the improvements you deliberately deferred so they don't get lost.
Behavioural questions
☺ Like you're 10: Stories about you — and the trick is having a few real ones ready, not inventing them on the spot.
These are not the soft part of the interview. In a discipline where things break on a schedule, how you behave when they break is the thing being hired. The frames below are deliberately written as scaffolding rather than as answers — the specifics have to be yours, because a story with no detail in it reads as invented, and interviewers ask follow-up questions specifically to find out whether the detail exists.
- Situation
- Two sentences. Where you were, what the system was, why it mattered. Not five minutes of context.
- Task
- What was specifically yours to do. "The team decided" is not a task; "I was on call and I owned the decision" is.
- Action
- The bulk of the answer, and in the first person singular. What you did, in order, including the thing you tried that didn't work.
- Result
- What happened, with a number if you have one — and what you'd do differently. The reflection is the part that separates a story from an anecdote.
The two failure modes: spending 80% of the answer on Situation, and using "we" throughout so the interviewer cannot tell what you personally did. Prepare four or five real stories that can each be told from different angles — one incident, one disagreement, one thing you improved unasked, one thing you got wrong — and most behavioural questions can be answered from that set.
🔴 "Tell me about a time you broke production."
What's being checked: whether you can own a mistake without either minimising it or performing guilt, and whether your instinct afterwards was to fix the system or to be more careful next time.
Frame. Situation: the change, why it looked safe. Task: that it was your change and you were the one who noticed or was paged. Action: what you did in the first ten minutes — and the strong version of this answer is "I mitigated before I diagnosed," because it shows the right reflex. Then how you communicated it, including telling people quickly rather than quietly trying to fix it first. Result: impact duration, and then the systemic follow-up: the missing test, the missing guardrail, the check that would have caught it. The reflection that lands is a change to the system, not a promise to be more careful — "I'll be more careful" is what someone says when they haven't understood why it happened.
Avoid: a story where the root cause turns out to be somebody else. If the honest answer involves another person's change, tell the version where your part is the focus.
🟡 "Tell me about a technical disagreement with a colleague."
What's being checked: whether you can disagree without it becoming personal, and whether you can be wrong gracefully. Interviewers are quietly assessing whether you'll be exhausting to work with.
Frame. Situation: the decision and the two positions, stated fairly — describe their position well enough that they'd recognise it. Task: your stake in it. Action: how you argued it — evidence you gathered, a prototype or a spike, a written comparison; how you escalated or didn't. Result: what was decided and how you behaved afterwards. A story where you lost the argument and then implemented the other decision well is often stronger than one where you won.
Avoid: a disagreement where you were obviously right and they were obviously foolish. It reads as unreflective, and interviewers have heard a lot of these.
🟡 "Tell me about a time you had to say no to a release."
What's being checked: whether you can hold a line under commercial pressure, and whether you did it in a way that left the relationship intact.
Frame. Situation: the deadline and what was riding on it. Task: what specifically made you uncomfortable — and be concrete, because "it didn't feel ready" is much weaker than "the rollback path hadn't been tested and the migration wasn't reversible." Action: how you raised it, who you raised it with, and crucially what alternative you offered. The strongest version of this answer includes an alternative: ship behind a flag, ship to a canary, ship the reversible half now. Saying no without an option is a blocker; saying no with an option is engineering. Result: what was decided, and whether your concern turned out to be right — including if it didn't.
🟡 "Tell me about something you improved that nobody asked you to."
What's being checked: initiative, and judgement about where to spend discretionary effort. Also whether you can finish something.
Frame. Situation: the recurring friction — a slow pipeline, a manual step, a noisy alert, a runbook that was wrong. Task: that you chose to take it on, and what you traded to do it. Action: how you made time, how you got buy-in without a mandate, how you avoided it becoming a rewrite. Result: the measurable change, and whether it stuck after you moved on — which is the question that separates a real improvement from a personal script nobody else uses.
Avoid: an unfinished side project. "I started building a tool to..." with no ending is a worse answer than a small thing you completed.
🔴 "Tell me about the worst incident you've been part of."
What's being checked: real on-call experience, and how you function when a lot of people are watching and nobody knows what's wrong.
Frame. Situation: what broke and what the user impact was. Task: your role — responder, IC, comms — and be precise, because "I helped" is not a role. Action: the timeline, including the wrong hypothesis you chased for twenty minutes, because every real incident has one and including it is what makes the story credible. How the decision to mitigate got made and by whom. Result: time to mitigate, time to resolve, and what came out of the review — the specific follow-up action, and whether it actually got done.
Avoid: a story where everything went smoothly. The interviewer is trying to find out how you behave when it doesn't.
🟢 "Tell me about a time you had to learn something quickly."
What's being checked: how you learn, which matters in a field where the stack changes underneath you. Also whether you know when to stop reading and start doing.
Frame. Situation: the thing you didn't know and why the deadline was real. Task: what you actually had to be able to do, which is usually narrower than "learn Kubernetes." Action: your method — the documentation you read, the throwaway environment you broke, the person you asked, the point at which you stopped reading and started building. Result: what you shipped, and what you deliberately deferred learning until later. That last part is the mark of someone who scopes well under time pressure.
🟡 "Tell me about working with a team that resisted a change you were driving."
What's being checked: whether you understand resistance as information rather than as an obstacle. This is the culture question in disguise, and it's asked because so much of this role is persuasion.
Frame. Situation: the change and who resisted. Task: your role in driving it. Action: and here's the move that makes this answer good — what you found out about why they resisted. Almost always it's rational: they'd been burned before, they'd carry the on-call cost, they had context you didn't, or the last three initiatives were abandoned halfway. What you changed about the plan in response. Result: where it landed, including partially.
Avoid: framing the other team as change-averse. It's the same reflex as blaming Ops for adding friction, and an interviewer who has been on the receiving end will hear it.
🟡 "What's a technical decision you now think was wrong?"
What's being checked: self-awareness, and whether you revisit your own decisions at all. A candidate with no wrong decisions has either not made many or not looked back.
Frame. Situation: the decision and the information you had at the time — and be fair to your past self, because "it was obviously wrong" is as unreflective as "it was fine." Task: that it was yours. Action: what you'd do differently and, more usefully, what signal you'd now look for earlier. Result: what it cost, and whether you've since changed how you make that class of decision.
Good territory: adopting a tool that didn't survive contact with the team; over-engineering something for scale that never arrived; under-investing in a rollback path; letting a manual step live longer than it should have.
Smart questions to ask them
☺ Like you're 10: The last five minutes, where you get to find out whether you'd actually want the job.
Ask questions you genuinely want the answers to — the transparently strategic ones are obvious and they waste your only chance to find out what the job is really like. Three or four is plenty. The ones below are specific to this discipline, and several of them will tell you more from how they answer than from what they say.
| Question | What the answer tells you |
|---|---|
| "What happens between a developer merging to main and that code being in front of a user? Walk me through it." | The single most informative question you can ask. You'll learn the branching model, the gate structure, the deployment strategy and roughly the lead time, all from one answer — and whether the person can describe their own pipeline. |
| "How often do you deploy, and what's the biggest thing standing in the way of deploying more often?" | The second half is the real question. A team that can name its own bottleneck is a team that's looked at it. |
| "Who carries the pager for this service, and what did last week look like?" | Whether "you build it, you run it" is real here, and whether on-call is sustainable or something people endure. Vagueness here is a signal. |
| "When something breaks, what does the review afterwards look like? Can you tell me about a recent one?" | Blameless in practice versus blameless as a word. Whether they can describe a recent incident comfortably tells you a great deal about the culture. |
| "How do infrastructure changes get made — is there a path that doesn't go through code?" | Whether IaC is enforced or aspirational. The honest answer is usually "mostly, except for..." and the exception is where the drift lives. |
| "What does the team do when the on-call is paged more than usual in a week?" | Whether reliability work competes fairly with feature work, or is always deferred to a quieter quarter that never arrives. |
| "Is there a platform team? If so, what do they own and what do product teams own?" | Whether the paved road exists, and whether the boundary is a service or a queue you'll be waiting in. |
| "What's something about the current setup that frustrates the team?" | A candid answer is a good sign in itself. "Nothing really" usually means either they haven't looked or they don't want to say. |
| "What would you want the person in this role to have changed six months in?" | Whether the role has a defined problem behind it or is a generic headcount req. It also tells you what you'd actually be measured on. |
| "How does this team decide to adopt a new tool?" | Whether decisions are made by evidence, by seniority, or by whoever pushed hardest. You will live inside this process. |
Compensation and on-call payment are entirely legitimate questions and this is usually not the stage for them — the recruiter or the offer conversation is, and asking there gets you a better answer from someone who can actually negotiate. And avoid asking a question whose answer is on their careers page or in the job description you were sent; it reads as not having read either.
The last week before the interview
☺ Like you're 10: A plan for seven days that doesn't involve trying to learn something new the night before.
The single most valuable rule for this week: do not learn new material. Anything you start on day three will be shallow by day seven, and shallow knowledge is worse than none, because it invites a follow-up question you can't answer. This week is for retrieval, for closing specific gaps you already half-know, and for arriving rested.
| Day | What to do | Roughly how long |
|---|---|---|
| Seven days out | Read the job description properly and map it against the topic map. Mark each domain honestly: solid, shaky, absent. The shaky ones are your week — the absent ones you'll handle by saying so in the room, which is a much better outcome than bluffing. | 1 hour |
| Six days out | Work the shaky domains: read the course lesson, then answer this page's questions for that domain out loud without looking. Cover the answer. Recognition is not recall, and only recall is tested. | 2 hours |
| Five days out | Write your stories. Four or five real ones — an incident, a disagreement, an unasked-for improvement, a mistake — in STAR bullets, not prose. Bullets, because you want to remember the shape rather than recite the words. | 1.5 hours |
| Four days out | One scenario question, out loud, timed at twenty minutes, using the five-step structure. Record yourself if you can stand it. Most people discover they skip straight to designing and never ask about constraints. | 1 hour |
| Three days out | Research them properly: what they build, what their stack looks like from the outside, any public engineering writing. Turn that into two of your questions for them. Then take the Self-Check across the domains you marked shaky. | 1.5 hours |
| Two days out | A full pass over the 🟢 warm-ups only, fast. These are the ones you should never fumble, and fumbling one early sets the tone for the whole hour. Then stop — do something else with the evening. | 45 minutes |
| The day before | Logistics: the link works, the room is quiet, the notes you're allowed are printed, the interviewers' names are noted. Re-read your own STAR bullets once. Sleep, deliberately. No new material. | 30 minutes |
| The day itself | Skim your STAR bullets and your questions for them. Nothing else. Cramming an hour before actively hurts recall, and the thing you learn at 8 a.m. is the thing you'll be least able to defend at 10. | 10 minutes |
- "Can I ask a couple of questions first?" — before any scenario question. It's expected, and skipping it is the most common scenario-round mistake.
- "I haven't used that, but here's how I'd reason about it." — the honest answer to a gap. It scores far better than a confident wrong answer, and interviewers are actively testing for whether you'll bluff.
- "The trade-off there is..." — after any recommendation. This is the single phrase that most reliably moves an answer from correct to senior.
- "Let me think about that for a second." — and then actually think. Silence is fine. Filling it while you work out what you believe is what makes an answer sound unsure.
Benny: I've got a screen tomorrow. I've been re-reading the Kubernetes networking docs all week.
Foxy: Does the job mention networking?
Benny: ...no. It mentions pipelines about six times.
Timmy: Then tell me what happens between a merge and a user, on the pipeline you actually built. Out loud. I'll time it.
Remy: And if they ask something you've never touched, just say so and say how you'd reason about it. That answer's fine. The made-up one isn't.
Sol: Also — when they ask, take the pause. Nobody has ever been marked down for thinking.
1. Without looking, state the difference between continuous delivery and continuous deployment, and name the single mechanism that separates them. 2. A candidate says "we use blue-green because it limits the blast radius of a bad change." What's wrong with that sentence? 3. Why does pointing a liveness probe at a database check cause an outage rather than preventing one? 4. You're asked to double deployment frequency this quarter. Give the two-sentence answer that neither refuses nor complies. 5. In a scenario round, what are the two steps most candidates skip — one at the start and one at the end?
Check your answers
- Continuous delivery means every change that passes the pipeline is verified and proven deployable at any time, with a human deciding when to release; continuous deployment removes that human gate so every passing change ships automatically. The mechanism separating them is a single manual approval step at the production-deploy stage — a
when: manualjob, a required environment reviewer, a Jenkins input step, or a manual sync policy. - Blue-green does not limit blast radius. The cutover is instant and total, so a defect that survived pre-cutover testing hits 100% of users the moment the switch flips. What blue-green gives you is near-instant rollback; capping blast radius is what canary does.
- A failing liveness probe restarts the container. If liveness depends on a downstream database, then every application instance fails it simultaneously during a brief database blip and the whole fleet restarts at once — often into a loop that prevents recovery. Liveness should test the process itself; a dependency being unavailable belongs in readiness, which removes the instance from rotation without destroying it.
- Something like: "I'd want to set the target on all four DORA metrics together rather than deployment frequency alone, because frequency on its own is trivially gameable by splitting one real release into ten trivial ones. Can we start from what problem the target is meant to solve — is it that features take too long to reach customers, or that each release carries too much risk?"
- At the start, asking clarifying questions about the problem and the constraints before designing. At the end, naming the trade-off the design makes and what you'd measure to find out whether it worked.
From here, the natural next steps in this course are the Self-Check for untimed recall across every domain, the flashcards for the definitional layer these warm-up questions test, the case study for a worked ninety-day transformation you can borrow the shape of when a scenario question asks how you'd sequence one, and the glossary for any term above you want pinned down precisely before you say it out loud in a room.