Use code SUMMERCODING at checkout for one month free Get Started →
All posts
Code QualityJun 20, 20268 min read

Code Review Checklist for Solo Developers

No team to review your code? Here is the checklist solo developers use to catch bugs, security holes, and bad patterns before shipping.

When you work solo, there is no second pair of eyes before code hits production. No PR reviewer to catch the off-by-one error you glossed over, the API route you left open, or the dependency you added at midnight and forgot to remove. That gap is not theoretical. It is where bugs accumulate, security holes open up, and technical debt starts compounding quietly beneath the surface.

Teams use code review to distribute that responsibility. Solo developers have to internalize it. That means building a habit of reviewing your own work before it ships, which turns out to be harder than it sounds, and running that review against a consistent checklist so the things that are easy to miss stay visible.

This is that checklist. Run it before you merge or deploy. It will not replace a second pair of eyes entirely, but it will catch most of what a reviewer would catch, and some things they would miss.

Why Self-Review Is Harder Than It Sounds

The core problem is context contamination. You wrote the code, which means you already know what it is supposed to do, and your brain fills in gaps automatically when you read it back. A reviewer reads the code as it actually is. You read it as you intended it to be. That gap is where bugs hide.

On top of that, you tested the happy path because that is the path you were thinking about when you built the feature. The inputs you tested were the inputs you expected. The edge cases you missed were the ones you did not think to try, which means they are also the ones you will not think to review.

The other trap is speed. When you are moving fast, code review feels like friction. You know the change is right, you just want to ship it. That instinct is exactly when review matters most, because the code you are most confident about is often the code that has the quietest assumption baked into it. Slow down by default, not just when something feels wrong.

The Checklist

Security

  • Hardcoded secrets. Check for API keys, tokens, passwords, or connection strings anywhere in the diff. If a value is sensitive and it is not coming from an environment variable, that is a problem. Search the diff for sk_, AKIA, password, secret, and token before committing.
  • Missing input validation. Every value that comes from outside your code -- user input, query parameters, request bodies, URL path segments -- needs to be validated before it is used. Check that types are enforced, lengths are bounded, and unexpected values are rejected early.
  • Exposed API routes. New endpoints need authentication checks. Look at every route added or modified in the diff and confirm that unauthenticated requests cannot access data or trigger actions they should not be able to.
  • Overly permissive CORS. If you added or changed CORS configuration, check that you are not allowing * on endpoints that return authenticated data or accept state-changing requests.
  • Unsanitized input in queries. Any user-supplied value going into a database query, shell command, or file path needs to go through a parameterized query or a dedicated sanitization function. String concatenation into SQL is an injection vulnerability. It does not matter if you trust the current callers.

Error Handling

  • Failed API calls. What happens when the external service returns a 500, times out, or returns a response in an unexpected shape? Look for every fetch, axios, or HTTP call in the diff and confirm there is handling for the failure case, not just the success case.
  • Empty database results. When a query returns zero rows, does the code handle that or does it crash attempting to access a property on undefined? Check every database call and look for assumptions that a result will always exist.
  • Third-party service timeouts. If you are calling a payment processor, email provider, or AI API, what happens if it takes 30 seconds to respond, or never responds? Make sure timeouts are set and that a hung request does not block a user-facing response indefinitely.
  • Unhandled promise rejections. In async code, every await that is not inside a try/catch is a potential uncaught rejection. Scan the diff for async functions and confirm that the paths where things go wrong are as handled as the paths where they go right.

Logic and Edge Cases

  • Empty arrays and collections. Does the code work when the list it is processing has zero items? Operations like .reduce() without an initial value, or accessing items[0] without checking length, will fail silently or throw on an empty array.
  • Null and undefined values. Trace through what happens when optional fields are missing. A function that works with a fully populated object often breaks when a single field is absent. Look for property accesses on values that might be null.
  • Off-by-one errors. Loops, pagination, array indexing, and date ranges are where these live. Check the boundary conditions: does the loop run one too many or one too few times? Does the page start at 0 or 1? Does the date range include or exclude the end date?
  • Behavior at zero and at scale. What happens when a count is zero, a price is zero, a quantity is zero? And what happens when there are ten thousand items instead of ten? Logic that works in the middle often breaks at the extremes.

Code Quality and Readability

  • Function size. If a function is doing more than one thing, it will be harder to test and harder to read. Look for functions that grew during this change. If you cannot describe what it does in one sentence, it is probably doing too much.
  • Naming. Variable and function names should say what they represent, not how they work. If a name needs a comment to explain it, the name is wrong. Read the diff for names like data, result, temp, or thing and replace them with something specific.
  • Duplicated logic. If the same logic appears twice in the diff, one of them should be a function. Duplication is not just a style issue -- it means that when the logic needs to change, there are two places to update instead of one, and you will miss one of them.
  • Dead code. Commented-out code, unused variables, unreachable branches, and imports that are no longer referenced should be deleted. They are noise that makes the real code harder to read.

Dependencies

  • Temporary packages that stayed. If you installed a package to test something and never removed it, it is in your dependency tree permanently now. Check your package.json diff against what you actually use in the code you are shipping.
  • Outdated packages. Before shipping a feature, run npm outdated or npm audit and check whether any packages in the critical path have available updates that address known issues.
  • Packages with known vulnerabilities. A package you added last month may have had a CVE published since then. npm audit catches most of these. Run it before you ship, not after.

A Simple Before-You-Ship Routine

The checklist above is most useful when it is applied to the diff, not to your memory of the code. Before you merge or deploy, pull up the exact changes that are going out and read through them as if you wrote none of it.

Then try to break it on purpose. Feed it bad input. Try an empty string where you expected a non-empty one. Try a negative number where you expected a positive. Try calling the endpoint without authentication. The things that break under bad input in testing are the same things that will break in production, because users will find inputs you did not think of.

Finally, look for anything you copy-pasted without fully understanding it. Copy-paste from Stack Overflow, from a previous project, or from a documentation example is how assumptions about context get imported silently. If there is a block of code you cannot explain line by line, that block deserves a closer look before it ships.

Read the diff like a stranger would. That stranger does not know what you intended. They only know what the code says.

Where Automation Helps

Manual review catches a lot. The problem is consistency. When you are the only person doing the review every single time, it is easy to skip steps when you are moving fast, tired, or just confident. The checklist items that feel obvious are the ones that get skipped most often, and those are exactly the ones that bite you.

Linters and static analysis tools handle the mechanical parts: unused variables, style inconsistencies, basic type errors. A pre-commit hook that runs these automatically means you do not have to remember to run them yourself. For security specifically, a tool like GitDoctor runs the same security checks automatically on every repo, so the things that are easy to miss in a self-review get caught before they ship.

Automation does not replace the judgment calls in a review. It handles the things that are checkable by a machine, which frees you to focus the manual review on the things that actually require thinking: the logic, the edge cases, the architecture decisions that only you know the context for.

Solo Does Not Mean Unreviewed

The instinct to skip review when you are working alone is understandable. You wrote the code, you know what it does, and you have already spent time on it. Review feels redundant.

But solo development does not eliminate the need for a second look. It means you have to be deliberate about being your own reviewer. That means using a consistent checklist, reading the diff cold, and testing the failure cases, not just the happy path. The bugs that reach production from solo projects are almost never the ones you thought were risky. They are the ones you were too close to see.

Build the review habit before you need it. The merge you skip reviewing is always the one that causes the incident.

Automate the checklist

Catch what manual review misses

GitDoctor scans your GitHub repository for security issues, exposed secrets, and bad patterns automatically. Each finding comes with an AI prompt to fix it. First scan is free.

Scan your repo