Job support8 min read

    Your first week in an unfamiliar codebase

    A day-by-day method for getting productive in a large or inherited codebase: run it, trace one request, read the history, find the landmines.

    You have been handed a codebase. It is large, it is old, the people who wrote it are gone, and someone would like an estimate by Thursday.

    The instinct is to start reading files. Do not start reading files. On any codebase of real size you will read for three days and retain almost nothing, because you have no framework to hang it on.

    What follows is an order that works — on your first week in a new job, on an inherited legacy project, or on an open-source repository you need to contribute to. It is built around one principle: understand how the thing runs before you understand how it is written.

    Day one: make it run

    Before reading a single line of business logic, get the application running locally.

    This feels like setup rather than learning. It is not. Getting it running teaches you more about the system's real shape than any amount of reading:

    • What it depends on — databases, queues, caches, external services.
    • How configuration works, and what is secret.
    • Which parts can run in isolation and which cannot.
    • What the team considers obvious, visible in whatever the README leaves out.

    Write down every step and every obstacle as you go. You are the last person who will ever see this project with fresh eyes, and that document is the single most valuable thing a newcomer can produce. It is also an easy, genuinely useful first contribution.

    If you cannot get it running by the end of day one, that is not a failure — that is your first finding, and it is worth reporting. A project that takes a week to set up has a problem that is costing the team on every onboarding and every new machine.

    Day one, later: find the entry points

    Every system has doors. Find them, and the map starts to form.

    Depending on what it is:

    • A web application: the route definitions. Usually one file or directory listing every URL.
    • An API: the route or controller registrations, or a specification file.
    • A scheduled system: the cron definitions, task registry, or scheduler config.
    • A queue consumer: the handler registrations.
    • A CLI: the command definitions.

    The list of entry points is your table of contents. It tells you what the system does — as a list of capabilities — without you reading any implementation. Skim it and notice which areas are large, which names repeat, and which sound like they matter.

    Day two: follow one request end to end

    Now pick exactly one thing the system does, ideally something central and simple, and trace it all the way through.

    A user logging in. An order being placed. A record being updated.

    Follow it: entry point, routing, middleware, handler, business logic, data access, response. Actually open each file. Do not skim.

    You are looking for the answers to questions that apply everywhere in the codebase:

    • Where do things live? Is logic in controllers, in services, in models? Every codebase has a convention, even the bad ones.
    • How does it talk to the database? An ORM, raw queries, a repository layer?
    • How are errors handled? Exceptions caught centrally, error values returned, or ignored?
    • How does authentication work, and where is the current user available?
    • What is the shape of the data? The two or three core entities everything else hangs off.

    One traced path gives you the pattern for fifty others. This is the highest-value day of the week, and it is worth resisting the pressure to be visibly productive while you do it.

    Sketch it as you go. Boxes and arrows on paper are fine. The act of drawing forces you to notice where you guessed.

    Day two, alternative: use the debugger instead

    If reading the path is slow going, run it instead. Put a breakpoint at the entry point and step through.

    You see the real call sequence rather than the one you inferred, the actual values rather than the expected ones, and every conditional that fired. For a confusing codebase this is often several times faster than reading, and it is dramatically underused.

    Day three: read the tests

    Tests are documentation that is verified to be true, which is more than most documentation can claim.

    Specifically:

    • Test names describe intended behaviour, frequently better than any comment.
    • Test setup shows you what a valid object looks like — often faster than reading the schema.
    • Edge-case tests are a list of the bugs this system has had before, which tells you where it is fragile.
    • Missing tests tell you where nobody is confident, and where you should be careful.

    If there are no tests, that is a significant finding about how much care any change will require.

    Day three, later: read the history, not just the code

    Version control history is the most underused resource in an unfamiliar codebase.

    Useful moves:

    Look at what changes most. Files with the most commits are either the heart of the system or its most troubled area. Either way, that is where your attention belongs.

    Read the commit messages around a confusing piece of code. The question "why on earth is it doing this?" is very often answered by a commit message from four years ago describing the bug this strange code prevents.

    Use blame on anything that looks wrong. Before you "fix" something odd, find out when and why it was added. A surprising amount of strange code is deliberate, and the strangest code is frequently the most load-bearing.

    Look at recent activity. Which areas are actively worked on, and which have been untouched for years? Untouched code is either stable or abandoned, and that distinction matters.

    Day four: find the seams and the landmines

    Now go looking for trouble deliberately, before it finds you.

    External dependencies. What does this system call that it does not control? Payment providers, email services, third-party APIs. Each one is a source of failures you cannot fix.

    Background work. Cron jobs, queue consumers, scheduled tasks. These are easy to miss when reading synchronous code and they cause the most confusing bugs, because things change without any request having happened.

    Anything with a warning comment. // do not change this, // hack, // TODO: fix properly. Read every one. They are a map of where the previous team knew there was a problem.

    Configuration differences between environments. Where does production differ from local? That gap is where bugs you cannot reproduce live.

    The oldest and largest file. There is usually one. Everyone is afraid of it. It probably contains something important.

    Day five: change something small

    Pick the smallest real change you can make and take it all the way through — write it, test it, review it, deploy it if you can.

    Not because the change matters. Because it teaches you the parts nobody writes down: how to run the tests, how review works here, what the deployment process is, what breaks in CI, how long it takes.

    Doing this in week one, on something trivially safe, means the first time you do it under pressure you have already learned where the friction is.

    Questions worth asking out loud

    If there is anyone still around who knows the system, these get you far more than a general "can you explain the codebase":

    • "What part of this breaks most often?" Straight to the fragile area.
    • "If I had to change one thing carefully, what would you tell me to watch out for?" Surfaces the hidden coupling.
    • "What would you rewrite if you had time?" Tells you what is known-bad, so you do not treat it as a pattern to imitate.
    • "Why is it done this way?" — asked without judgment. There is often a good reason, and if there is not, you have just found something.
    • "What is not written down anywhere?" The most valuable question you can ask anyone leaving a project.

    What to write down as you go

    Keep one document. It does not need to be neat.

    1. Setup steps, including everything that went wrong.
    2. The system in five sentences. What it does, for whom, and what the main pieces are. If you cannot write this by Friday, keep tracing.
    3. A traced path, as a diagram.
    4. The core data entities and how they relate.
    5. Landmines — the fragile areas, the warning comments, the things people told you.
    6. Open questions, which is the most useful list of all. Review it at the end of week two and note how many answered themselves.

    Two weeks later this document is the onboarding guide the project never had. It costs you nothing extra to produce, because you were going to learn these things anyway.

    What to resist

    Do not rewrite anything yet. Code that looks wrong is frequently code you do not understand. The strangest-looking lines are often the most necessary ones. Wait until you can explain why it is the way it is — then you have earned the right to change it.

    Do not read the whole codebase. You cannot, and you will not retain it. Depth on one path beats breadth across all of them.

    Do not trust the documentation over the code. Read it, then verify. Documentation drifts; the code is what actually runs.

    Do not assume the conventions are deliberate. Some are careful design decisions. Some are what the first developer happened to do in 2019, copied ever since. Asking which is which is a good use of someone's time.

    Do not stay silent because you feel slow. Everyone is slow in an unfamiliar codebase. A week of quiet struggle looks worse to a team than a good question on day two.

    If there is nobody to ask

    Sometimes the previous team is entirely gone. No handover, no documentation, no institutional memory. That is a common situation and it is genuinely harder — the archaeology is all you have, and there is nobody to confirm your reading.

    In that case the history, the tests and the debugger are not just useful, they are your only sources, and it is worth being slower and more systematic than you would otherwise be.

    It is also a reasonable point to get a second pair of eyes. Working through an inherited system with someone who has done it before is one of the more useful forms of technical support — not to have the work done for you, but to have someone check your reading of a system where being wrong is expensive.

    Common questions

    Small, well-structured projects can be a few days. Large or legacy systems are realistically weeks before you are comfortable, and that is normal rather than a reflection on you. What should happen in the first week is narrower: you can run it, you can trace one path through it, and you have shipped one small change end to end.

    Not until you can explain why it is the way it is. Code that looks wrong is very often code you do not yet understand, and the strangest-looking lines are frequently preventing a bug someone hit years ago. Check the version control history first — the commit message usually answers the question.

    Then the version control history, the tests and a debugger are your sources. History tells you why things changed, tests describe intended behaviour in a form that is verified, and stepping through execution shows the real call sequence rather than the one you inferred. Be more systematic than usual, and write down what you learn as you go.

    Want this looked at properly?

    Bring the actual blocker from the actual project. We will work through it with you so you understand the fix, not just the patch.

    Ask on WhatsApp

    Related services

    Keep reading

    All articles