Your Legacy Code Isn't the Problem, Your Attitude Is
How I stopped romanticizing rewrites and learned to build software that actually lasts
Ever catch yourself scrolling through tech Twitter, seeing someone’s tweet about their shiny new project built with the latest framework, perfect TypeScript configs, and a pristine git history with meaningful commit messages? And you think, “God, I wish that was me.”
Meanwhile, you’re staring at a 10-year-old codebase that’s held together with duct tape, prayers, and what appears to be the coding equivalent of a fever dream. There’s a function called doStuff() that’s 847 lines long. The previous developer left comments in three different languages. And somehow, somehow, the entire checkout process depends on a global variable named $YOLO.
Yeah. I feel you.
Why We’re All Chasing the Shiny
Let’s be real about why greenfield projects are so damn appealing. They represent everything we wish our current work could be:
Clean slate, clean conscience. No one’s judging your architectural decisions because, well, there aren’t any yet. You get to be the genius who sets up the perfect folder structure, the one future developers will praise.
Modern tech stacks. You can finally use that framework you’ve been reading about. The one with the beautiful documentation and the enthusiastic Reddit community. Not the ancient library you’re currently using that has three Stack Overflow answers, two of which are from 2009 and marked as “deprecated.”
The hero fantasy. Deep down, we all want to be the developer who built something from scratch. The one who can say, “Yeah, I architected that entire system.” It feels more impressive than saying, “I maintain a PHP application that processes insurance claims.” (Shout out to those that do)
But here’s what nobody tells you about greenfield projects: they’re the developer equivalent of getting a puppy. Sure, it’s cute and exciting at first. But in six months, you’re the one cleaning up the mess.
The Uncomfortable Truth About Greenfield Projects
New projects become legacy code faster than you think. Like, way faster.
That perfect architecture you spent three weeks planning? In production for six months and already accumulating technical debt because business requirements changed and deadlines got tight. That clean codebase? Now has a temp folder that’s definitely not temporary anymore. Those meaningful git commits? Replaced by “fix bug” and “it works now idk” because you were deploying at 11 PM on a Friday.
Every greenfield project is just legacy code in its larval stage.
And here’s the kicker: if we just keep chasing the new stuff, how are we ever learning what actually works and what doesn’t? We’re building things and then throwing them away before we can see the consequences of our decisions. That’s not how you get better at this craft. That’s just how you get really good at starting projects.
Think about it. You can’t learn what scales until you’ve maintained something at scale. You can’t understand the true cost of your abstractions until you’ve had to debug them at 3 AM when everything’s on fire. You don’t know which patterns actually survive contact with real users until, well, real users have been using them for a while.
What Legacy Code Actually Teaches You (No, Really)
Okay, time for some real talk. Working on legacy code sucks sometimes. I’m not going to pretend it doesn’t. Debugging someone else’s terrible code is about as fun as doing your taxes while getting a root canal.
But, and this is a big but, maintenance work teaches you things that greenfield projects never will.
Problem-solving under constraints. You can’t just rewrite everything. You can’t just “use a better framework.” You have to work within the reality of what exists. And figuring out how to make meaningful improvements without burning everything down? That’s a skill that transfers everywhere.
Understanding why code exists. That horrifying doStuff() function? There’s probably a reason it’s 847 lines long. Maybe not a good reason, but a reason. Learning to read code archaeologically, understanding the business logic buried in the mess, teaches you more about real-world software development than any tutorial ever will.
The art of incremental improvement. You can’t boil the ocean. You can’t fix everything at once. So you learn to make things better one small piece at a time. Refactor one function. Add tests to one module. Extract one service. This is how actual progress happens in the real world.
Appreciating boring, reliable systems. That legacy codebase you hate? It’s probably making someone money. Like, actual money. It’s processing real transactions, serving real users, and keeping the lights on. There’s something deeply valuable about software that just works, even if it’s not exciting.
The Reality Nobody Talks About
Most development work is maintenance. That’s just the reality. Greenfield projects are rare because successful software requires ongoing support. When something works well enough to stick around, guess what? It sticks around. And someone has to maintain it.
You know what’s actually rare? Software that gets to stay greenfield for long. Most projects either fail (and get abandoned) or succeed (and become legacy). Pick your poison.
The developers who can bring craftsmanship and discipline to messy codebases often create more lasting value than the ones chasing perfect abstractions in greenfield projects. Because they’re solving real problems with real constraints, not theoretical ones.
Look, I get it. Complaining about your legacy codebase feels good. But bitching about code you can’t change is just burning energy you could use to actually make something better. The question isn’t “How do I escape this legacy hell?” The question is “What can I improve right here, right now?”
Finding Your Opportunities
Every codebase, yes, even yours, has areas you can incrementally enhance without full rewrites:
That one module everyone’s afraid to touch? Document it. Add some tests. Make it slightly less scary. You’re not fixing it all today, but you’re making it better for the next person (who might be you in three months).
The configuration that’s scattered across twelve files? Consolidate it. Even if you can’t fix everything, fixing one thing makes the next fix easier.
The process that’s slower than it should be? Profile it. Find the bottleneck. Maybe you can’t rewrite the whole thing, but shaving 30% off the runtime is still a win.
These aren’t sexy. They won’t get you retweets. But they’re the kind of work that makes software better over time. And honestly? There’s a certain satisfaction in taking something messy and making it just a little bit cleaner.
The Question You Should Be Asking
So here’s what it comes down to: when you’re fantasizing about that greenfield project, what problem are you actually trying to solve?
Are you trying to solve real business problems? Technical problems that are genuinely blocking progress? Or are you just bored and chasing the dopamine hit of npm create new-framework?
Because here’s the thing: if the problem is “this codebase is old and not fun to work in,” a greenfield rewrite probably isn’t the answer. The answer might be making the current codebase less painful. Bit by bit. Day by day.
But if the problem is “this architecture fundamentally can’t do what the business needs,” okay, that’s different. Sometimes you do need to rebuild. Sometimes the codebase is so critical to the business that you can’t afford to just throw it away and start over. You have to do incremental updates and maintain it because there’s so much going on. You can’t afford the downtime. You can’t afford to bet the company on hoping a new framework will magically solve your problems.
The real skill isn’t knowing how to build from scratch. It’s knowing when you should and when you shouldn’t. It’s understanding that ideally, we’re building things that will last. Things that we’ll need to refactor and update, sure, but things that have staying power.
A Different Kind of Craftsmanship
Maybe the answer isn’t escaping legacy code. Maybe it’s changing how you think about it.
What if instead of seeing maintenance work as “not as good as greenfield,” you saw it as a different kind of challenge? What if the mark of a good developer isn’t just being able to start projects, but being able to sustain them?
People don’t pay for things to just throw them away a year or two from now. They pay for software that works. Software that lasts. Software that can grow and adapt as their needs change. And the developers who can deliver that—who can take something messy and make it better, who can work within constraints and still find ways to improve things—those are the developers who create real value.
So yeah, greenfield projects are nice when you can get them. They’re fun. They’re exciting. But don’t sleep on the lessons hiding in that legacy codebase. Don’t underestimate the value of being the person who can make existing things better.
Because at the end of the day, the codebase you maintain today is training you for the projects you’ll build tomorrow. And maybe, just maybe, understanding how to work with legacy code is what will help you write code that won’t become someone else’s nightmare down the road.
Quote of the Day:
Don’t seek for everything to happen as you wish it would, but rather wish that everything happens as it actually will—then your life will flow well.” - Epictetus
👉 If you enjoy reading this post, feel free to share it with friends!
Or feel free to click the ❤️ button on this post so more people can discover it on Substack 🙏
You can find me on X and Instagram.
Also, I just launched a new YouTube channel - Code & Composure


