Latest / The Tech Career Podcast with Fexingo: Engineering Jobs, Interviews, and FAANG Career Strategy / How FAANG Engineers Navigate Large Legacy Codebases
Transcript
- Lucas: You join a FAANG team, first day, you get access to the repository — and it's fifteen years old, three million lines of code, zero unit tests, and the original author left the company before you graduated college. What do you do? Luna: That's basically the onboarding experience for a lot of engineers. It's not the greenfield project they show you in the interview. Lucas: Exactly. And the interview process tests you on system design from scratch — design Twitter, design Uber. But once you're inside, your job is usually the opposite: make sense of what already exists, change it without breaking it, and somehow stay sane. Luna: So where do you even start? Do you read the whole thing? Lucas: That's the trap. I've seen new grads try to read the entire codebase line by line. It's impossible. Instead, you start with the read path — the main request flow. For a web service, that means: a request comes in, hits the controller, goes to the service layer, touches the database, returns a response. Trace that one path end to end. Luna: So you ignore ninety percent of the code on purpose. Lucas: On purpose. You can't afford to learn everything. You need the skeleton first. Once you understand the read path — which usually lives in about five percent of the files — you can start adding tests around it. And those tests become your documentation. Luna: I've heard that term — 'test as documentation.' Can you unpack that? Lucas: Sure. In a legacy codebase, the comments are often wrong, the wiki is outdated, and the architecture docs are aspirational. But tests — if you write them — are executable. They never lie about what the code actually does. So when I join a new team, my first pull request is rarely a feature. It's adding integration tests around the most critical user flow. Luna: And that gives you the confidence to change things later. But what about the social side? Like, who owns which part of the code? Lucas: Ownership in a legacy monolith is often a mess. There's a concept called 'code ownership through file-level CODEOWNERS' in GitHub. But in practice, most files have no owner, or the listed owner is a team that was renamed three reorgs ago. So you have to build a dependency graph. Luna: How do you do that? Lucas: Tools like Dependency-Check or even a simple script that parses imports. I once ran a graph analysis on a service at my last company — seven hundred files, and one single file was depended on by three hundred others. That file had no tests and one author who had left years earlier. That's your bus factor right there. Luna: So you start by identifying the high-risk, high-traffic files. Lucas: Exactly. You pick the top five most-depended-on files and you add tests around them. That's the highest-leverage work you can do in a legacy codebase. It's not glamorous, but it's the work that actually reduces risk. Luna: And does that kind of work get recognised in performance reviews? I've heard engineers worry that cleaning up technical debt doesn't show up as a 'launch.' Lucas: It can, if you frame it right. You don't say 'I refactored the payment service.' You say 'I reduced the time to ship the payment feature by forty percent because I added integration tests that caught regressions in ten minutes instead of three days.' That's a measurable impact. Luna: So it's about tying your cleanup to a business metric. Lucas: Right. And there's another career angle. Becoming the expert on the oldest, ugliest part of the codebase actually gives you leverage. People need you. When production breaks and nobody knows how the billing cron job works, you're the one who can fix it. That's job security. Luna: But isn't there a risk you get typecast as 'the legacy person' and never get to work on new stuff? Lucas: It's a real risk. The way to avoid it is to set a time limit. I tell engineers: spend your first two months learning and cleaning. Then ask to rotate onto a project that uses the legacy system in a new way. You bring your deep knowledge, but you also get to build something fresh. Luna: That's a good strategy. What about the debate between rewriting versus refactoring? I've seen teams spend years planning a rewrite that never ships. Lucas: The rewrite is almost always the wrong call. There's a famous article by Joel Spolsky — 'Things You Should Never Do, Part One' — where he talks about Netscape's disastrous rewrite. The existing code has years of bug fixes, edge cases, and tribal knowledge baked into it. A rewrite throws all that away. Luna: So you advocate for incremental refactoring. Lucas: Always. You pick one module, you extract it into a microservice or a library, you put tests around it, and you release it. Then you do the next piece. It's slower, but it actually ships. At Google, the SRE teams have a concept of 'error budgets' — you can spend a certain amount of downtime on refactoring. That's a good framework. Luna: Let's talk about a specific example. Have you worked on a legacy system that was particularly bad? Lucas: I once joined a team that maintained a billing service written in PHP — and the team was all Java engineers. No one wanted to touch it. The original author had left, but the code was still running, processing millions of dollars in transactions every month. It had no tests, no CI, and the deployment process was a shell script that the original author had never documented. Luna: That sounds terrifying. How did you approach it? Lucas: First, I added a monitoring dashboard. We had no idea if the service was healthy. Then I wrote a single integration test that called the most critical endpoint — the one that processes a payment — and checked the database. That test caught a regression the very next week when someone accidentally changed a column name. Luna: And that built trust with the team. Lucas: Exactly. After that, the team started adding their own tests. Within three months, we had coverage on all the critical paths. We never rewrote it. It's still running today, probably. Luna: So the key is to make the codebase a little better every time you touch it. The Boy Scout rule. Lucas: Leave it cleaner than you found it. That's the mantra. And it applies to documentation too. When you figure out how a piece of code works, write a comment — not 'what' but 'why.' The 'what' is in the code. The 'why' is lost history. Luna: That's a great point. Speaking of lost history, are there any tools you recommend for understanding legacy code? Lucas: For Java, I like Structure101 or even just IntelliJ's dependency analysis. For Python, Pylint with its dependency graphs. But the most underrated tool is git blame. It tells you who last touched a line. If you see a line that hasn't been touched in five years, you know it's either rock solid or a ticking time bomb. Luna: And what about the human side? How do you deal with engineers who are defensive about their old code? Lucas: That's delicate. You never say 'this code is terrible.' You say 'I'm trying to understand the intent behind this — could you walk me through it?' Most people want to be helpful. And once they see you improving it, they become allies. Luna: So legacy code is more of a people problem than a technical problem. Lucas: A lot of engineering is. But the technical part is solvable if you take it step by step. And there's a career superpower here: if you can learn to work effectively in a legacy codebase, you can work anywhere. Because most codebases are legacy. Luna: Right. The shiny greenfield stuff is the exception. Lucas: And if today's conversation gave you something usable, consider supporting the show. We keep it ad-free and listener-supported. If you find value in episodes like this, you can buy us a coffee at buy me a coffee dot com slash fexingo. It's a small gesture that helps us keep doing this. Luna: Yeah, it really does make a difference. Every bit of support lets us focus on bringing you practical, honest conversations like this one. Lucas: So back to legacy code — I think the biggest takeaway is: don't be afraid of it. Approach it with curiosity, add tests as you go, and leave it better than you found it. That's how you build a reputation as someone who gets things done. Luna: And that reputation is what gets you promoted. Lucas: Exactly. Thanks for listening, and we'll see you next time.