Slow Dispatch

← Back to essays

The shape of a good pull request

3 min read updated

I've reviewed about ten thousand PRs. The good ones look almost identical. Here's the shape — what to put in the diff, the description, and what to leave on the floor.


I’ve reviewed about ten thousand PRs across five companies. After a while you notice that the good ones look almost identical, and the painful ones rhyme.

The good shape is small. It does one thing. The description tells you why, what changed, what didn’t, and what to look at first. It has fewer than three “rebased” commits and zero “fix typo” commits because the author squashed before they pushed. The reviewer can be done in fifteen minutes.

The painful shape is the opposite of all of those things.

The five things a good PR description has

A good PR description is roughly five paragraphs:

  1. One sentence on the user-visible outcome. Not “refactor X” — “Users now see Y when they Z.” If the PR has no user-visible outcome (refactor, infra), this is “We can now safely do Y, which we couldn’t before, because…”
  2. One paragraph on the why. What was the actual problem? What evidence did you use to identify it? What did you rule out? This is the section reviewers will skip if it’s too long, so write it tight.
  3. One paragraph on the how. The mental model. Not the diff — the diff is right there. The idea the diff implements.
  4. One paragraph on what’s risky. Be honest. “I’m 70% sure the cache invalidation is correct; if I’m wrong, the symptom would be stale reads on the X endpoint.” Reviewers can prioritize. Stakeholders can plan rollouts.
  5. One paragraph on what’s NOT in this PR. This is the most underrated section. “I did not change the migration, I did not touch the auth path, I did not optimize the query.” It saves the reviewer ten “did you also consider…” questions.

If you write all five and it’s still longer than your screen, the PR is too big. Split it.

The diff itself

The diff that ships smoothly tends to:

  • Touch one logical thing. Not “one file” — one idea. Renaming a variable in 12 files is one idea, one PR. Adding a feature plus a refactor is two ideas, two PRs.
  • Have a clear “main file” — the place where the substantive change lives. Reviewers should be able to look at one file and understand 80% of the PR.
  • Have its tests in the same diff. If “tests in a follow-up PR” appears in the description, the follow-up doesn’t happen.
  • Have not been rebased seventeen times against an actively-changing main. If you have to constantly rebase, your PR has been open too long, and that is its own problem.

What to leave out

Some things should be in your branch but not in this PR:

  • Drive-by formatting changes in unrelated files.
  • “While I was here” refactors.
  • Commented-out code that you “might want later.” You won’t.
  • Console logs. Even ones that “are clearly temporary.”

These don’t help the reviewer. They make the diff larger and the intent fuzzier. Keep your branch clean and ruthlessly focused.

The reviewer’s side

If you are the reviewer of a PR like this — small, well-described, single-purpose — your job is to read it carefully, ask sharp questions, and approve quickly. The single biggest cause of PRs sitting open for a week is reviewers who feel they need to find something to comment on. You don’t. If the PR is good, say so, and move on. The author will trust your reviews more, not less.

If you are the reviewer of a PR that is the painful shape — large, vague, three changes in a trench coat — the right move is almost always to ask the author to split it. Not “could you maybe pull out the refactor?” — “I can’t review this responsibly. Please split into A, B, and C and I’ll prioritize them.” This feels rude. It is not. The kindest thing you can do for an author who is shipping painful PRs is to teach them, immediately, that this is the bar.

The good PR is a craft skill. It compounds. People who write them ship more, faster, and with fewer regressions, for their whole career.