NNabeel Hassan

Blog · October 11, 2026 · 8 min read

Inheriting a Codebase: What I Check in the First Week Before Changing Anything

By Nabeel Hassan — AI Engineer · ICPC World Finalist

TL;DR: When you inherit a codebase someone else built, do not start by reading code and do not start by rewriting anything. Spend the first week answering five questions in order: can I build and ship it myself, where does the truth live, what do real users touch most, what breaks silently, and who holds the knowledge that is not written down. Only after that do you have the right to decide what to fix, what to leave alone and what to rebuild. I have walked into live products more than once, most visibly stepping in as CTO at RAQTS during a critical phase across Unity, React Native and Next.js, and giving CTO-level guidance on an existing React, TypeScript and GraphQL app for Amazon sellers at Bettershop. The checklist below is what I actually do in that first week.

Founders usually call me at one of two moments. Either the original developer or agency has left and nobody fully understands the system anymore, or the product is live, growing, and every release feels like it might break something. In both cases the founder wants to know the same thing: is this codebase salvageable, and what should we do first?

The honest answer is that you cannot know from reading the code. You know from running it, shipping it and watching where it hurts. That is what the first week is for.

Rule zero: do not rewrite anything in week one

Every engineer who inherits a codebase feels the pull to rewrite it. The code looks unfamiliar, the conventions are not yours, and some of it is genuinely bad. But unfamiliar is not the same as wrong, and a rewrite started before you understand why the code looks the way it does will faithfully reproduce the bugs the original team already fixed, minus the fixes.

When I came into RAQTS, the platform was already live with players and facilities using it. The first job was not to make it beautiful. It was to map what already worked well enough not to break it, which I wrote about in stepping in as CTO mid-build. You earn the right to change a system by understanding it first.

So the first week is read-only in spirit, even if you fix a typo or two. Here is the order I work in.

1. Can I build and ship it myself?

Before anything else, I try to go from a clean machine to a running build, and then from a code change to something a real user could receive. This sounds basic. It is the single most revealing test of an inherited project.

What I am checking:

If I cannot ship it, nothing else matters yet. A product you cannot release is a product you cannot fix.

2. Where does the truth live?

Every product has a handful of facts it cannot afford to get wrong. For a sports platform it is a player's score and position on a leaderboard. For an analytics app for Amazon sellers it is the profit figure, which means how fees and returns are modelled. For a voice agent business it is the lead record in the CRM.

For each of those, I trace where the authoritative version lives and how many places compute or store a copy. The most common serious problem I find in inherited products is not ugly code. It is the same fact being calculated in two or three places that have quietly drifted apart: the mobile app shows one number, the web portal another, and the backend a third.

On RAQTS the fix direction was to make the backend the single source of truth for live leaderboards, with the Unity Lumo layer, the mobile apps and the web portal all rendering it rather than deciding it. On the Bettershop dashboard the expensive decision was the data model behind profit, which I covered in building a GraphQL admin dashboard for Amazon sellers. In both cases, getting the truth in one place mattered more than any refactor of the UI code around it.

By the end of this step I can usually draw the product's data flow on one page. If I cannot, that itself is the finding.

3. What do real users actually touch?

Not every part of a codebase deserves the same attention. A messy admin settings screen that one person opens once a month is not a priority. A messy checkout, sign-up or booking flow that every user passes through is.

I look at analytics if they exist, support messages, store reviews and, where I can, I just use the product the way a customer would. The goal is a short list of the three to five paths that carry the business. Those are where I want the code to be boringly reliable, and where any refactoring budget should go first.

This is also where I find out whether the product has analytics worth trusting at all. Inherited products often track events that were named by three different people in three different styles, and some of them fire twice. Knowing that early stops you from making decisions off broken numbers.

4. What breaks silently?

Loud failures get fixed because somebody complains. Silent failures sit for months. In an inherited system I specifically hunt for the places where something can go wrong and nobody would notice:

Silent failures are where the real risk in an inherited codebase usually lives, so they get the most time.

5. Who knows what is not written down?

Every system has knowledge that only exists in someone's head: why a strange workaround exists, which customer has a special configuration, which setting must never be changed. If the original developer is still reachable, even for a paid hour or two, that conversation is the most valuable hour of the week. I go in with a list of the oddest things I found and ask why each one is there.

If they are not reachable, the git history, old tickets and old chat threads are the next best thing. A commit message from two years ago explaining a hack is worth more than the hack itself.

I write all of it down in the repository, not in my notes. The point of the exercise is that the next person, including me in three months, does not have to rediscover it.

What comes out of the week

At the end of the first week I give the founder a short written assessment, not a slide deck. It usually has four parts:

  1. Keep as is. The parts that work well enough and do not justify the risk of change. This list is usually longer than founders expect, and that is good news.
  2. Fix now. Account ownership, release blockers, silent failures with real business impact, and any place where the truth is computed in more than one location.
  3. Improve as you go. Code quality problems in the high-traffic paths, cleaned up alongside feature work rather than in a separate project.
  4. Rebuild, maybe. The rare part where the cost of keeping it is clearly higher than replacing it, with an honest estimate. Most of the time this list is empty or has one item.

That structure keeps the conversation away from "is the code good or bad", which is not a useful question, and toward "what do we do on Monday", which is.

Why this works across very different stacks

I have done this on a sports-tech platform spanning Unity, React Native and Next.js, on a React and GraphQL analytics app, on cross-platform SDK work at Geonode, and on voice agent systems built by other people. The stacks have almost nothing in common. The questions are identical.

That is the same reason I can hold several fractional CTO roles without relearning everything each time. The durable skill is not knowing a particular framework. It is knowing what to look at first, in what order, and having the discipline not to touch anything until you understand why it is the way it is.

If you have just inherited a product, or you are a founder whose developer has moved on, resist the urge to rewrite and resist the urge to panic. Spend a week finding out what you actually have. It is almost always more salvageable than it looks on day one.


I step into existing products as a fractional CTO and engineer, across web, mobile, Unity, XR and AI agent systems, for founders in the US, UK and Europe. If you have inherited a codebase and want a clear read on what to keep, fix and rebuild, more about my background is here, or book a call.

FAQ

What should I do first when I inherit a codebase?

Prove you can build and release it yourself from a clean machine, and confirm the company owns every account: app stores, cloud, domain, DNS and payments. A product you cannot ship is a product you cannot fix, so this comes before reading or changing code.

Should I rewrite an inherited codebase?

Rarely, and never in the first week. Unfamiliar code is not the same as wrong code, and an early rewrite tends to reintroduce bugs the original team already fixed. Most inherited products are better served by fixing the high-risk areas and improving code quality alongside feature work.

What are the biggest hidden risks in an inherited product?

Silent failures: unmonitored background jobs, third-party webhooks and syncs that swallow errors, old mobile app versions breaking after backend changes, and the same business figure computed in several places that have drifted apart.

What should a codebase audit deliver to a founder?

A short written plan in four parts: what to keep as is, what to fix now, what to improve gradually alongside feature work, and what, if anything, is worth rebuilding, with an honest estimate. It should answer what the team does on Monday, not just whether the code is good.

Building something in this space?

I take on AI-agent, automation and product work directly — scoped fast, shipped fast.

Book a discovery call →

Keep reading