The first time you inherit a codebase, the instinct is to open the editor and start reading. Folder by folder, file by file, forming opinions. By Wednesday you have a list of things you hate and a vague plan to rewrite the worst of them.
I have done that, and it is the wrong first week. Reading code tells you what the code says. It does not tell you what the product does, where it hurts, or which ugly part is ugly for a reason. You find those out by running it, shipping it and watching where it breaks.
I have walked into live products more than once: stepping in as CTO at RAQTS, a sports-tech platform running across Unity, React Native and Next.js, giving CTO-level guidance on a React, TypeScript and GraphQL analytics app for Amazon sellers at Bettershop, plus cross-platform SDK work and voice agent systems other people built. The stacks have almost nothing in common. The first week looks the same every time: five questions, in this order.
Rule zero: no rewrites in week one
Unfamiliar is not the same as wrong. Code that looks strange often looks strange because it absorbed a bug report you have not read yet. Rewrite it before you understand it and you will faithfully reproduce the original bugs, minus the fixes.
When I came into RAQTS, players and facilities were already using the platform. The first job was not to make it beautiful. It was to map what already worked well enough that I should not break it. I wrote that story up in Nobody Hands You Day One, and the longer argument about why rewrites go wrong late rather than early is in Rewrites Do Not Fail in Month One.
So week one is read-only in spirit. Fix a typo if you must. Do not touch the architecture.
1. Can I build and ship it myself?
Before anything else I go from a clean machine to a running build, and then from a one-line change to something a real user could receive. It sounds basic. It is the most revealing test of an inherited project.
- Clone and run using only what is in the repo and the docs. Every undocumented step gets written down as I hit it: the secret that lives on someone's laptop, the manual database seed, the exact tool version that silently matters. (I have a whole post on this, Your README Is a Lie Until Someone Else Runs It.)
- Who owns the accounts? App Store Connect, Google Play Console, the cloud provider, the domain and DNS, the payment provider, analytics. On a product with mobile apps, losing the store accounts is worse than any code problem. The company should hold the keys, not a contractor who left in spring.
- Can I produce a release? For web, can I deploy. For mobile, can I produce a signed build, and do we actually have the signing keys and certificates. For Unity, does a build pipeline exist or does it live in one person's editor. That last one is why I keep pushing for a boring Unity pipeline before tests.
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. On a sports platform it is a player's score and leaderboard position. On an analytics app for Amazon sellers it is the profit figure, which really means how fees and returns are modelled. On 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 calculated in two or three places that have quietly drifted apart: the mobile app shows one number, the web portal another, the backend a third. Nobody notices until a customer screenshots two of them side by side.
On RAQTS the direction was to make the backend the single source of truth for live leaderboards, with the Unity layer, the mobile apps and the web portal rendering it rather than deciding it. On Bettershop the expensive decision was the data model behind profit, which is the subject of Your Dashboard Is Just a Data Model Wearing a Chart. In both cases, getting the truth into one place mattered more than any refactor of the UI around it.
By the end of this step I can usually draw the product's data flow on one page. If I cannot, that is the finding.
3. What do real users actually touch?
Not every file deserves the same attention. A messy settings screen that one admin opens once a month is not a priority. A messy sign-up, checkout or booking flow that every user passes through is.
I look at analytics if they exist, support messages and store reviews, and I use the product the way a customer would. The output is a short list of the three to five paths that carry the business. That is where the code needs to be boringly reliable, and where any refactoring budget goes first.
This is also where you learn whether the analytics deserve trust at all. Inherited products often have events named by three different people in three different styles, and a couple that fire twice. Finding that early stops you from making week-two decisions off broken numbers.
4. What breaks silently?
Loud failures get fixed because somebody complains. Silent ones sit for months. So I go hunting specifically for places where something can fail and nobody would know:
- Background jobs. Crons, queues, sync jobs, webhook handlers. Are they monitored? If one stopped running last Tuesday, how would anyone find out? A green checkmark on a scheduled job only tells you the process exited cleanly, not that it did any work.
- Third-party boundaries. Payment webhooks, CRM syncs, email and SMS providers. These fail at the edge, and the failure is often swallowed by a catch block that logs to nowhere. Related: a webhook tells you something happened, not that you have everything.
- Old app versions. Mobile users do not all update. If the backend changed shape, the build from eight months ago may be failing for a slice of users who will never file a bug. More in The App Version You Shipped in March Is Still Calling Your API.
- Error reporting. Is there crash reporting on mobile and error tracking on the backend, and is anyone reading it? A dashboard full of ignored errors is a backlog nobody prioritised.
This step gets the most time, because this is where the real risk usually lives.
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 reachable, even for a paid hour or two, that conversation is the most valuable hour of the week. I bring a list of the oddest things I found and ask why each one is there.
If they are gone, git history, old tickets and old chat threads are the next best source. git log -p on the weirdest file in the repo is underrated. A two-year-old commit message explaining a hack is worth more than the hack.
And I write all of it down in the repository, not in my own notes. The point 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 I hand the founder a short written assessment, not a slide deck, in four buckets:
- Keep as is. Parts that work well enough that changing them is not worth the risk. This list is usually longer than founders expect, which is good news.
- Fix now. Account ownership, release blockers, silent failures with real business impact, and anywhere the truth is computed in more than one place.
- Improve as you go. Code quality in the high-traffic paths, cleaned up alongside feature work instead of in a separate "refactor sprint" that never ends.
- Rebuild, maybe. The rare part where keeping it clearly costs more than replacing it, with an honest estimate. Most of the time this list is empty or has one item.
That structure moves the conversation away from "is the code good or bad", which is not a useful question, toward "what do we do on Monday", which is.
The part that transfers
What surprised me over several of these is how little the framework knowledge mattered. Unity, React Native, Next.js, GraphQL, C# SDKs, voice agents: none of the five questions changes between them. The durable skill 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 just inherited a product, resist both urges: the urge to rewrite and the urge to panic. Spend a week finding out what you actually have. In my experience it is almost always more salvageable than it looks on day one.
What is the first thing you check when you open someone else's repo? I am curious whether anyone starts somewhere other than the README.
Originally published on nabeelbaghoor.com.
Top comments (0)