Code Review and Working with Existing Codebases Questions
Reviewing others' code and navigating unfamiliar systems: giving and receiving actionable review feedback, spotting correctness and design issues, and reading and understanding large or legacy codebases before changing them. Covers collaborative coding norms, incremental change in shared repositories, and verifying changes against existing behavior. The team-facing side of day-to-day engineering.
You are a senior engineer faced with many teams disagreeing about a shared code style standard for new language adoption. Describe your leadership approach to reach a decision: how to gather input, weigh technical trade-offs, pilot the standard, communicate the change, and measure adoption while minimizing disruption.
Sample Answer
Direct answer
I treat this as a decision-making process problem, not a technical one: gather input broadly but make the actual call with a small accountable group, pilot the standard on a real team before mandating it org-wide, communicate the reasoning and not just the rule, and measure adoption with an honest, mechanically-enforced signal rather than assuming a written standard changes behavior on its own.
Structured elaboration
Gather input
Survey affected teams for their current conventions and actual friction, not just preferences, so the decision is grounded in real problems (for example, "our formatter conflicts with theirs when we share a monorepo") rather than taste. Reduce the debate to 2-3 genuinely competing proposals rather than open-ended bikeshedding; most style disagreements collapse to a small number of real axes, like import ordering or naming convention.
Weigh technical trade-offs
Favor whichever option has the strongest tooling support (an existing auto-formatter, mature editor integration, linter support) over one that's marginally nicer but manual to enforce, since manual enforcement is where standards quietly die. Weigh switching cost too: a team with a large existing codebase in the new language has more sunk cost in its current convention than a team just starting out.
Pilot before mandating
Pick one or two willing teams to adopt the standard for a real sprint or two, not a toy example, and explicitly ask what broke, what felt like friction, and what they'd change before finalizing anything.
Communicate the decision
Publish the reasoning, not just the rule: why this option over the alternatives, and what trade-offs were accepted. Give a clear timeline, a grace period, and name who to raise disagreement with.
Measure adoption and minimize disruption
Track adoption through the automated formatter or linter's own pass/fail rate in CI (continuous integration, the automated build/test pipeline) across repos, an honest signal since it's mechanically enforced rather than self-reported. Roll out with tools that fix code automatically instead of requiring manual compliance, the single biggest lever for minimizing disruption. Grandfather existing code with format-on-touch (only reformat files as they're naturally edited) rather than one disruptive mass reformat that breaks blame history and floods review queues.
Worked example
Three teams adopting a new backend language disagree on import-ordering and error-handling conventions. I run a two-week input-gathering round: two teams prefer style A, matching their existing microservices; one team already has 40,000 lines in style B, a shared library they don't want to rewrite. Rather than forcing a binary choice, I pick style A as the org standard, since it has better tooling support (an existing auto-formatter plugin), but scope the rollout as format-on-touch: new and touched files get reformatted automatically by CI, while untouched legacy files in the third team's library keep style B until they're naturally edited, with a linter configuration that doesn't flag the legacy files. I publish a short doc explaining the tooling reasoning and the grandfather policy, pilot on the first team for two weeks, adjust the auto-formatter's import-grouping rule after they report false-positive linter noise, then roll out to the other two teams. I track adoption as the percentage of touched files in each repo that pass the new formatter in CI, which climbs past 90% within a month without anyone manually reformatting anything.
Trade-offs and pitfalls
- Forcing a big-bang reformat of an entire existing codebase creates a disruptive diff that breaks
git blameand swamps review queues; format-on-touch avoids this at the cost of a longer period of inconsistency - Deciding by committee vote often produces a compromise nobody's tooling actually supports well; weigh tooling maturity heavily, not just preference counts
- Skipping the pilot and mandating org-wide immediately is the most common way this backfires, since the standard hasn't been tested against a real team's actual workflow
- Publishing a rule without publishing the reasoning breeds quiet non-compliance; people follow standards they understand the "why" of far more reliably
A reviewer used harsh language in comments and the author felt publicly humiliated. As the engineering manager, describe a stepwise plan to de-escalate the situation, repair relationships, update code review guidelines, and prevent similar incidents, including any coaching, documentation changes, and follow-up measurements.
Sample Answer
Direct answer
As the engineering manager, act on two tracks at once: repair the specific relationship and any public harm quickly and privately, and separately fix the guidelines or process so this failure mode doesn't repeat. Treat a single conversation as the start of the fix, not the end of it, and check back later.
Structured elaboration
- Talk to the author first, 1:1. Acknowledge the harm directly without minimizing it, and ask what they need right now, whether the comment should be edited or removed, or whether they'd prefer a different reviewer on this PR (pull request).
- Talk to the reviewer separately, not in a group setting. Be direct that the language was out of line regardless of whether the underlying technical point was right, and get their perspective, rushed, frustrated, unaware of tone, without treating that as an excuse for the impact.
- Repair publicly if the harm was public. If the comment was visible to the team, a short, genuine acknowledgment of what happened is worth more than a vague "let's all be kind" message that erases the specifics; the goal is for the team to see it was actually addressed.
- Close the structural gap. Check whether the team's review guidelines say anything about tone and conduct at all. If they don't, that's a process gap, not solely the reviewer's individual failure, and it's the manager's job to close it, e.g. adding an explicit norm plus example phrasing (this is a nit, this is blocking, avoid absolute language like "this is terrible") to the team's review guide.
- Coach, don't just discipline, for a first occurrence. Work through concrete feedback practices together: phrasing comments about the code rather than the person, leading with a question instead of a command, labeling severity explicitly so a blocking issue doesn't read as optional, and pairing any criticism with a specific alternative rather than a bare complaint. Consider having the reviewer shadow reviews from someone whose feedback style already does this well. If this turns out to be a repeat pattern, it escalates beyond coaching.
- Follow up and actually measure it. Check in with the author privately again a couple of weeks later, not just once, to see if the relationship genuinely repaired rather than just went quiet. Watch later review threads for whether tone actually changed; a guideline that's written down but never checked tends to fade.
Worked example
A reviewer writes something like "this is embarrassing, did you even test this" on a junior engineer's PR, visible to the whole team channel. The manager messages both people privately within the day, has the reviewer edit the comment, and posts a short, honest acknowledgment in the channel rather than a vague platitude. The team's review guide gets an explicit tone section with example blocking-versus-nit phrasing. Two weeks later, the manager checks in privately with the junior engineer, not just assuming things are fine because nobody's raised it again.
Trade-offs and pitfalls
Over-correcting into a heavily policed review culture, where people are afraid to say anything critical, is its own failure mode; the goal is honest, direct feedback delivered respectfully, not conflict avoidance. Treating this as purely an individual coaching issue without fixing the guideline gap means the next person makes the same mistake. Treating it as purely a documentation fix without a real conversation with both people leaves the actual relationship unrepaired.
You're leading a code review where a proposed optimization reduces latency by 30% but reduces readability and increases maintenance cost. As the architect, decide whether to approve, require changes, or reject. Describe your decision process, the metrics you require, and how you'd document and communicate the final choice to the team.
Sample Answer
My default on a gain like this is "require changes," not outright approval, unless the latency win is tied to a concrete, currently-missed service-level agreement (SLA, the response-time commitment the team is held to) or a measurable cost reduction, because a benchmark-only win is not worth trading away code the next engineer cannot safely touch. This is not a single yes or no; it is a risk-weighted call I make from specific metrics, and the decision has to be written down, not just remembered.
Metrics I require before deciding
- Before and after latency at p50, p95, and p99 (the median, 95th-percentile, and 99th-percentile response time), from a reproducible benchmark, not a one-off run.
- Throughput, CPU and memory delta, and error or retry rate, so a latency win is not hiding a resource or reliability regression.
- A maintainability delta: lines changed, new invariants the code relies on, and whether test coverage went up or down for the touched path.
Decision process
I weigh whether the latency win connects to a real business signal, an SLA the team is currently missing, or a cost reduction from needing fewer instances, against a benchmark-only improvement nobody downstream will notice. If it connects to a real signal, I lean toward approval with the trade-off documented. If it is benchmark-only, I lean toward requiring simplification. My default landing on most proposals like this is "require changes": keep the algorithmic win, but ask for the new invariants to be made explicit in comments or a short design note, tests added for the edge cases the optimization introduces, and a staged or canary rollout with monitoring before it reaches the main path.
Documenting and communicating the choice
I write a short architecture decision record (ADR) capturing the trade-off and the metrics behind it. If any debt is knowingly accepted, it becomes a tracked ticket with an owner and a timeline, not just a comment in the PR thread. I then communicate the decision and its reasoning to the team, and to product or sales if a customer commitment is affected, so the trade-off is visible instead of buried in a merged diff.
Worked example
Suppose the optimization touches a checkout API path. The benchmark shows p95 latency dropping from 220ms to 154ms, exactly the claimed 30% reduction (220 times 0.7 equals 154). But the team's SLA for that path is 300ms, so the path was never breaching it: there is no customer-visible or contractual benefit today, though the drop may reduce the number of instances needed at peak, which is worth pricing out separately rather than assuming. Meanwhile the diff introduces three new invariants relied on by dense bit manipulation, with no added tests. Because the SLA is not at risk and the code adds real, untested complexity, I would require changes: keep the performance work, add tests around the new invariants, document why the code is structured this way, and land it behind a canary rollout with latency and error dashboards watched before a full rollout.
Trade-offs and pitfalls
Being reflexively strict about readability can miss the case where the 30% is the exact fix for an SLA a paying customer is breaching right now, so the framework has to run on the real numbers each time, not as a fixed rule. Accepting the change with a debt ticket that never gets prioritized is functionally the same as silently accepting the debt, so the ticket needs a real owner and date, not just an entry in a backlog. Rejecting outright is rarely the right call when the performance work is real: it discourages future optimization contributions and just pushes similar code back through review with less scrutiny next time, since the author learns to route around review rather than through it.
Leadership: You're in a large engineering org where reviewers are overloaded and PR latency is high. Propose a scalable manual-review strategy combining automation, triage, reviewer assignment rules, and code ownership. Explain how to maintain quality while reducing time-to-merge and preventing reviewer burnout.
Sample Answer
Direct answer
At org scale, "review faster" doesn't work, the fix is redesigning how review load is distributed: automate everything mechanical before a human ever opens a diff, route each pull request (PR, a proposed code change submitted for review) to the right owner instead of a free-for-all queue, triage by risk so low-risk changes take a lightweight path, and make reviewer load a metric leadership actually watches, the same way they'd watch on-call load.
Structured elaboration
Automation removes load before a human sees the diff
- Continuous integration (CI, the automated build/test pipeline) blocks on lint, type checks, unit tests, and coverage delta, so reviewers never comment on things a machine already caught
- A bot flags PR size and touched-file risk (for example, "this modifies auth middleware") so a reviewer knows what they're walking into before opening it
Triage by risk
- Classify changes into tiers: low-risk (docs, config, isolated feature-flagged code) gets a single reviewer or even auto-merge after CI passes; medium risk gets normal review; high-risk (shared libraries, security, data migrations, billing) gets a mandatory named owner plus a second reviewer
- This concentrates scarce senior reviewer attention on what actually needs it instead of spreading it thin and evenly
Reviewer assignment and code ownership
- CODEOWNERS-style routing (a config file mapping directories to the team or person who owns that code) auto-assigns based on what the PR actually touches, instead of a random queue
- Load-balance assignment within an ownership group (round robin or least-loaded) instead of everyone requesting the one person known to be thorough
- Rotate a weekly "on-call reviewer" role per team so load doesn't permanently concentrate on the same two or three people
Preventing burnout while cutting time-to-merge
- Cap how many PRs a single reviewer is expected to have open at once, visible on a shared dashboard
- Protect a daily review block instead of letting review compete with deep work as constant interrupts
- Track reviewer load as a first-class metric leadership actually looks at, not an afterthought
Worked example
An org of 300 engineers has PR latency (open to merge) at a median (the middle value, half of PRs merge faster and half slower) of 3 days, driven by 15% of reviewers absorbing 60% of review volume, the people everyone requests because they're known to be thorough. The plan: introduce CODEOWNERS-based auto-assignment for the 20 highest-traffic directories, add a bot that classifies PRs into risk tiers from touched paths and diff size, and set a rule that low-risk PRs need one reviewer with a 4-business-hour service-level agreement (SLA, an explicit response-time target) while high-risk PRs need a named owner with a 1-business-day SLA. Leadership adds a dashboard showing open-review-count per person, and anyone over a threshold (say, 8 open reviews) gets rebalanced by their lead. After a quarter, median latency for low-risk PRs drops sharply because they no longer queue behind high-risk items, and concentration on the top reviewers eases because ownership-based routing spreads assignments across each team instead of funneling everything to a few known-good individuals.
Trade-offs and pitfalls
- Automated risk-tiering can misjudge risk (a one-line change to a rate limit is "small" but dangerous), keep a human override on the classification
- CODEOWNERS routing can create silos where only the "owner" ever reviews a path, losing the cross-pollination review normally provides; rotate ownership periodically
- Cutting time-to-merge by lowering the bar (fewer required reviewers everywhere) trades quality for speed; the real lever is distributing existing rigor better, not removing it
- A reviewer-load dashboard used punitively instead of for rebalancing damages trust fast; be explicit it's a load-balancing signal, not a performance metric
That is every published Code Review and Working with Existing Codebases question for Engineering Manager so far. Browse the other topics in this category, or practice this one interactively.