After this lesson, you will be able to: Give and receive code review feedback constructively, write PR descriptions that communicate intent, and use code review as the team's main quality lever.
Code review is the single highest-leverage activity in most engineering teams. Done well, it catches bugs, transfers knowledge, and builds shared standards. Done poorly, it's a bottleneck that drains morale.
A good reviewer asks: does this code do what the PR description says? Does it do it safely? Does it leave the codebase in a better or at least equal state? Good reviewers spot: missing error handling, security concerns, broken invariants, style drift, missing tests, and unclear naming. Good reviewers don't: rewrite the author's code in comments, demand stylistic changes outside the PR's scope, or block on personal preferences.
WHY this change exists (link to the bug, ticket, or feature spec). WHAT the change does, in plain English, one paragraph. HOW you verified it works (tests added, manual repro steps, screenshots). RISKS the reviewer should think about (db migration, feature flag, deploy ordering). A reviewer who can answer 'why am I looking at this?' in 10 seconds reviews 3x faster.
Paste this into your repo's .github/PULL_REQUEST_TEMPLATE.md.
## WhyLinks to ticket: <jira/linear/github URL>Short context: 1-2 sentences on the user / business problem.## What- Bullet list of code-level changes- Anything renamed or moved- Migrations or env-var changes## How verified- [ ] Unit tests added/updated- [ ] Integration test passes locally- [ ] Manual repro steps (with screenshots if UI)## Risks- DB migration: yes/no, reversible: yes/no- Feature flag: <flag name> or 'no flag'- Deploy ordering required: yes/no## Out of scope (intentional)- Anything related you noticed but didn't fix in this PR.
Comment on the code, not the person. 'This loop is O(n^2) on user count, consider a Set' beats 'this is bad'. Distinguish blockers (must fix) from nits (preference). Many teams prefix nits: 'nit: extra blank line'. Suggest, don't dictate. 'Have you considered…' invites discussion; 'change this to…' shuts it down. Praise non-obvious good choices. Reviewing isn't only about catching mistakes.
Treat every comment as a question, not an attack. When you disagree, articulate why; don't just push back or accept silently. When you're wrong, say so explicitly. Senior engineers admit mistakes faster than juniors. Update the PR, don't bury the feedback. Each round should make the diff better, not just longer.
Run this on any PR over ~50 lines.
Read the PR description first; if you can't tell what it does in 10 seconds, ask the author to rewrite
Look at the test changes BEFORE the code changes; tests describe intended behavior
Read the code in the order: types/interfaces → public functions → internal helpers
Check for: missing error handling, untrusted input, off-by-one errors, race conditions
Check the diff for accidental commits: console.logs, debug code, hardcoded secrets, commented-out blocks
Check migrations and env-var changes against the description
Leave any blockers as 'Request changes'; nits as comments; questions as comments
If the PR is too big, say so and ask for a split; don't review 1000-line PRs
Rubber-stamping. If you don't have time to review, say so; don't approve blindly. Reviewing every line and missing the architecture issue. Step back periodically. Bikeshedding (arguing about trivial style). Lock formatting choices in Prettier; review the substance. Holding PRs forever. A stale PR is a bug magnet; review within a day if you can. Treating review as a gate, not a conversation. Pair on the hard ones in person or on a quick call.
Pick the most useful first action.
Sign in and purchase access to unlock this lesson.