The fastest way to make a technical answer sound generic is to rehearse it without a real change in front of you. Pick a pull request you can explain, spend 10 minutes turning its diff into a walkthrough, and you will have concrete decisions, risks, and verification steps to discuss instead of a memorized architecture speech.
This is not a trick for performing expertise you do not have. It is a way to surface work you already did: why the change exists, where it can fail, and what evidence would make you trust it.
Why use a PR instead of an interview prompt?
Interview prompts are intentionally underspecified. A real pull request is the opposite: it contains constraints. There are files, tests, callers, migrations, and review comments. That makes it a useful rehearsal artifact.
For a 45-minute technical interview, a strong answer usually needs four things:
| Part | What the interviewer can learn | Evidence you can point to |
|---|---|---|
| Context | Why the work mattered | Issue, incident, or user path |
| Decision | Why this approach won | Constraints and rejected options |
| Safety | How you controlled risk | Tests, compatibility, rollout plan |
| Outcome | What you checked afterward | Metrics, logs, or manual verification |
The mistake is reading the diff line by line. A reviewer can do that alone. Your job is to connect the changes to the system behavior.
A ten-minute rehearsal loop
Use this sequence once per PR. It is deliberately short enough to repeat.
- Minute 0–2 — name the before-and-after. Write one sentence: “Before, X happened when Y; now, Z.” If you cannot make that sentence concrete, you are not ready to explain the change.
- Minute 2–4 — choose the risk. Pick the one failure that would matter most: a stale write, an authorization bypass, a breaking API response, or a dropped background job. Do not list every theoretical risk.
- Minute 4–7 — narrate the control. Explain the code path that prevents or exposes that failure. Mention the test or observable signal that backs it up.
- Minute 7–10 — answer one follow-up. Ask yourself what you would change at 10× traffic, with an older client, or after a retry.
Generate the questions from a real diff
The script below is intentionally small. It reads the names of files changed against a base branch and produces follow-up prompts based on likely risk areas. It does not inspect source code or claim to understand your system. You supply the context; the script makes it harder to skip the important questions.
Save it as pr-walkthrough.mjs, then run:
git fetch origin main
node pr-walkthrough.mjs origin/main
import { execFileSync } from "node:child_process";
const base = process.argv[2] ?? "origin/main";
let raw;
try {
raw = execFileSync("git", ["diff", "--name-status", `${base}...HEAD`], {
encoding: "utf8",
});
} catch (err) {
console.error(`Could not compare ${base} with HEAD.`);
console.error("Fetch a base branch with shared history, then try again.");
console.error("Example: git fetch --deepen=100 origin main");
process.exit(err.status ?? 1);
}
const rules = [
[/^(src|app|pages)\//, "Which user-facing behavior changes, and how would you verify it manually?"],
[/(api|router|route|server)/i, "What is the request contract, and which old callers could break?"],
[/(db|schema|migration|prisma|drizzle)/i, "Can old and new code run against this data shape at the same time?"],
[/(auth|permission|role|token|session)/i, "Who is allowed to take this path, and how is that checked on the server?"],
[/(test|spec)\./i, "Which failure would this test catch that a happy-path demo would miss?"],
[/(queue|worker|job|cron)/i, "What happens on retry, duplicate delivery, or a partial failure?"],
];
const files = raw.trim().split("\n").filter(Boolean).map((line) => {
const [status, path] = line.split("\t");
return { status, path };
});
if (!files.length) {
console.error(`No changes found against ${base}. Fetch the base branch or pass a different ref.`);
process.exit(1);
}
const questions = new Map();
for (const file of files) {
for (const [pattern, question] of rules) {
if (pattern.test(file.path)) questions.set(question, (questions.get(question) ?? 0) + 1);
}
}
console.log(`# PR walkthrough: ${files.length} changed file${files.length === 1 ? "" : "s"}`);
console.log("\n## Start with the change");
for (const { status, path } of files.slice(0, 12)) console.log(`- ${status}: ${path}`);
if (files.length > 12) console.log(`- …and ${files.length - 12} more`);
console.log("\n## Rehearse these follow-ups");
for (const [question, matches] of questions) console.log(`- (${matches} file${matches === 1 ? "" : "s"}) ${question}`);
console.log("- What did you deliberately leave unchanged, and why?");
console.log("- What observable signal would tell you the rollout is safe?");
Here is what a useful result looks like for a change that touches an API route, a database migration, and tests:
# PR walkthrough: 4 changed files
## Rehearse these follow-ups
- (1 file) What is the request contract, and which old callers could break?
- (1 file) Can old and new code run against this data shape at the same time?
- (1 file) Which failure would this test catch that a happy-path demo would miss?
- What did you deliberately leave unchanged, and why?
- What observable signal would tell you the rollout is safe?
That output is a prompt sheet, not a script you should recite. Answer every line with a detail visible in the PR. “We added a migration” is not enough; “the new column is nullable first, so the old worker can continue writing while the backfill runs” is an explanation a teammate can challenge productively.
Turn one change into a concise answer
Suppose the change adds an idempotency key to a payment endpoint. A vague answer sounds like this:
“I made the endpoint retry-safe and wrote tests.”
The rehearsal version has a shape:
“Retries from the client could create two charges when the response was lost. I stored a key plus a request fingerprint before calling the provider, so the same key and payload return the first result while a conflicting payload is rejected. The test starts two requests with the same key and asserts one provider call. In production, I would watch duplicate-charge support tickets and the rate of key conflicts; an unexpected rise in conflicts suggests a client bug rather than a successful retry.”
Notice the answer is still short. It establishes a cause, a control, a proof, and a signal. If the interviewer asks about multi-region writes or provider timeouts, you now have a real boundary to discuss instead of inventing one.
What to do when the PR is too large
Large diffs create bad rehearsal sessions because they invite a tour of unrelated files. Narrow the artifact before you practice:
- Select one user journey, such as “checkout after a network retry.”
- Select one invariant, such as “a completed order is charged exactly once.”
- Select one proof: a test, a dashboard, or a manual reproduction.
- Put the remaining changes in the “what I would cover next” bucket.
This is also a good way to answer “tell me about a challenging project” without wandering through three months of work. You can say which slice you are choosing and why it best demonstrates the trade-off.
Practice the follow-up, not just the opening
The best self-check is to ask a hostile-but-fair question after each answer:
| If the interviewer asks… | Do not say… | Try explaining… |
|---|---|---|
| “Why not just retry?” | “Retries are bad.” | Which action is safe to repeat, which one is not, and where the deduplication record lives. |
| “How did you test that?” | “I added unit tests.” | The exact precondition, failure mode, and invariant the test asserted. |
| “What would you do differently?” | “I would improve it.” | The constraint that would justify a different design: scale, consistency, cost, or time to recover. |
Record one run, then listen for two failure modes: unsupported claims (“it was more scalable”) and missing evidence (“we monitored it”). Replace either with a concrete number, test name, log field, or user behavior from the work.
If you want a structured place to repeat these sessions, aceround.app — an AI interview assistant can be useful for running a mock round. Bring the PR and your own evidence; treat any feedback as a prompt to sharpen the explanation, not as a substitute for understanding the change.
Sources and disclosure
- The command interface used here follows the Git documentation for
git diff. - AI assistance was used for copyediting. The workflow and code were reviewed and tested by the author.
Top comments (0)