How to Review Your Own Code (When There's Nobody Else)
At Home Depot, every PR got reviewed by at least one other engineer. At Sage Ideas, I'm the only engineer. Nobody reviews my code.
This is a problem. Not because I write bad code — but because I'm blind to my own assumptions. Every developer is.
I've developed a self-review process that catches most of what a second pair of eyes would. It's not perfect, but it's dramatically better than "looks good, merge."
The 24-Hour Rule
I never review code I wrote today. The minimum gap between writing and reviewing is 24 hours. Ideally 48.
This sounds slow. It's actually fast. In those 24 hours, I'm building something else. When I come back to review, I've partially forgotten my implementation. That forgetting is the point — it lets me read the code like someone else wrote it.
The Review Checklist
I review in 4 passes. Each pass looks for different things:
Pass 1: Read Like a User (5 minutes)
Don't look at the code. Open the PR diff and read just the file names and line counts.
Questions:
- Does the change make sense from the file names alone?
- Is it touching too many files? (sign of a coupled change)
- Are there files that shouldn't be in this change?
Pass 2: Read for Logic (15 minutes)
Now read the code. But don't check for style, naming, or formatting. Just logic.
Questions:
- Does the happy path work?
- What happens with null/undefined inputs?
- Are there any cases where this fails silently?
- Am I handling the error case, or just logging and moving on?
- Is there a race condition? (Especially in async code)
Pass 3: Read for Security (10 minutes)
``` For every input from outside the system, ask:
- Is it validated?
- Is it sanitized?
- Could it be used for injection (SQL, XSS, command)?
- Could it be used to access another user's data?
- Am I exposing more data than necessary in the response? ```
Pass 4: Read for the Next Person (5 minutes)
Pretend someone new joins the team tomorrow. Would they understand this code?
Questions:
- Are variable names clear without context?
- Is there a comment explaining WHY (not what) for non-obvious logic?
- Is the function name a lie? (Does `getUser` actually create a user if none exists?)
- Is there a simpler way to do this?
The Git Diff Trick
I don't review in my editor. I review in GitHub's PR diff view — even for solo PRs.
Why? My editor shows me the whole file with all its context. The diff shows me ONLY what changed. That's what I need to review.
I actually PR against myself:
```bash
Create a branch for every change
git checkout -b feature/add-billing-webhook
... do the work ...
git push origin feature/add-billing-webhook
Create a PR on GitHub
gh pr create --title "Add billing webhook handler" --body "..."
Review the PR diff in GitHub's UI
Merge when satisfied
```
This gives me the PR URL, diff view, and a record of every change with context. Six months from now, I can find the PR where I added billing.
The Rubber Duck Upgrade
Instead of talking to a rubber duck, I write a one-paragraph summary of what the change does and why. If I can't explain it in one paragraph, the change is too complex and needs to be split.
This paragraph becomes the PR description. It serves double duty.
What I Still Miss
Let me be honest about what self-review doesn't catch:
- Assumptions I didn't know I had. I once implemented timezone handling assuming all users were in EST. It took a user from California to find it.
- Performance issues at scale. My test data is 100 rows. Production has 100,000. I miss O(n²) problems regularly.
- Better approaches I'm not aware of. A reviewer who's used a library I haven't will suggest better solutions. Self-review can't add knowledge I don't have.
For these, I compensate with: integration tests on real-ish data, performance monitoring in production, and regularly reading other people's code on GitHub.
Solo engineering without code review is risky. Solo engineering without SELF code review is reckless.