Move Fast Without Breaking Things !
How to Deliver Fast and maintain quality, through Refactoring, Feature Flags, and Automation
Every software engineer knows the drill. A new feature request lands on your desk with a deadline that feels like it was set yesterday. You roll up your sleeves, knowing that delivering on time might mean cutting corners — skipping tests, hardcoding a value, or hacking together a quick fix. It feels great when the feature goes live, but weeks later, when the bug reports flood in, you wonder: was moving fast worth breaking things?
The reality is that engineering is a constant tug-of-war between speed and quality. Move too fast, and you build a house of cards that collapses at the worst time. Focus too much on perfection, and you risk being labeled “too slow.” But here’s the thing: speed and quality aren’t opposites. You don’t have to choose one over the other. Let’s dive into how you can move fast and build maintainable systems that won’t come back to haunt you.
Why “Move Fast and Break Things” Doesn’t Work
“Move fast and break things” became the go to philosophy for innovation during the startup boom. But for anyone who has worked on a live production system, this philosophy often feels like a disaster waiting to happen.
I have worked at a startup where the default was to ship fast. I once did a hotfix to show a loading indicator in a page no one uses. Adopting this philosophy means you are turning away from solving problems and becoming a feature factory with no consideration of data. After a while, we ended up with a product that always had bugs, very hard to fix, and slow to add features to. Our focus became to get what’s on production to run, with time we lost purpose and that was our only focus. The startup went bankrupt.
A more sustainable approach that could have saved the company would have been to prioritize long-term velocity. High-quality code may take slightly longer to ship, but it pays off by reducing the time spent fixing bugs, cleaning up spaghetti code, or firefighting in production.
Plan for Refactoring From the Start
Here’s a truth every engineer needs to embrace: shortcuts are inevitable. Deadlines, pivots, and last-minute changes happen, and sometimes you need to cut corners to deliver on time. The problem isn’t taking shortcuts — it’s treating them as permanent.
To balance speed with quality, start with the mindset that every shortcut is temporary. Log these quick fixes as tech debt tasks in your backlog, and prioritize them like you would a new feature. When planning sprints, allocate time to clean up code.
Think of it like writing a to-do list. If you borrowed code from Stack Overflow to hit a deadline, make sure to revisit it later and implement a proper solution. Engineers who plan for refactoring from day one build systems that evolve gracefully instead of breaking down. From my experience , agreeing with product managers on 10% of sprint velocity for refactoring is reasonable and would help maintain the codebase quality.
Focus on Containing the Mess
If you have to cut corners, make sure the mess doesn’t spread. When writing quick fixes or hacks, isolate them within specific modules, components, or files.
For instance, if you’re hardcoding a value for a quick demo, keep it in a clearly labeled config file or a single function. This makes it easier to find and replace later. The key is to keep these shortcuts localized, so they don’t become landmines scattered across your codebase.
One of my former teammates called this “putting the mess in a drawer.” It’s still there, but at least you know where to find it.
I follow the same approach for A/B tests, as there is a chance we will remove them if the test failed. I try to keep them isolated for easy cleanup and less affected area when we do. I would recommend doing the same for urgent requests. It will make refactoring much faster, and less likely to break things.
Feature Flags for Safe Iteration
Feature flags are a game-changer when you need to ship fast without sacrificing quality. By wrapping new features in a flag, you can deploy unfinished work to production safely. This lets you test with a small group of users, gather feedback, and iterate without risking the entire system.
For example, if you’re rolling out a new search feature, a feature flag allows you to enable it for 5% of users while monitoring performance. If something goes wrong, you can turn it off instantly without needing a rollback.
Feature flags give you the freedom to experiment without turning your production environment into a testing ground.
Automate Testing and Use CI/CD Pipelines
Nothing kills speed like regressions. You’ve shipped a feature, moved on to the next task, and suddenly, an old bug reappears. Now you’re stuck fixing it instead of building something new.
Automated tests and CI/CD pipelines are your best defense against this chaos. integration tests ensure modules play nicely together, and end-to-end tests validate user workflows.
Think of these as a safety net. They might take time to set up, but they let you move quickly without fear of breaking things. Plus, they make you look like a rockstar when you catch a bug before it reaches production.
Manual Regressions from QA can take a day or 2 for them to be done properly, without automation a lot of corners will be cut when a request is urgent causing a domino effect of bugs and hotfixes
Dedicate Time for Refactoring (Refactoring Fridays)
One of the simplest ways to balance speed and quality is to schedule time for maintenance.We discussed the 10% block. I experimented with that by introducing “Refactoring Fridays” — a day dedicated to paying down technical debt. No feature work, no distractions — just pure cleanup.
This practice worked wonders. Developers looked forward to Fridays because it gave them the breathing room to tidy up messy code and fix things they’d been meaning to address. The result? A healthier codebase and a happier team.
We did not dedicate the entire day but each engineer blocked a couple of hours in their calendar to clean up.
We also had another practice where we did mob programming as a team once a month for an hour to refactor a part in the system. This increased collaboration, team morale and our code base health.
Set Clear Priorities with Stakeholders
Engineers often face pressure from stakeholders to deliver faster. But here’s a pro tip: speed and quality don’t have to be at odds if you communicate effectively.
When discussing timelines with stakeholders, explain the trade-offs of cutting corners. For example:
“We can deliver this feature in two weeks, but to meet that deadline, we’ll take some shortcuts that will require cleanup later. Alternatively, we can spend an extra week building it properly, which will save us time in the long run.”
By framing the conversation around business outcomes (e.g., reduced risk, better performance), you can gain stakeholder buy-in for balanced timelines.
Speed and Quality Are Not Opposites
Balancing speed and quality isn’t just possible — it’s essential for sustainable development. By planning for refactoring, isolating quick fixes, leveraging feature flags, and automating tests, you can deliver fast without sacrificing maintainability.
Remember, moving fast doesn’t mean rushing blindly. It means being intentional about where you take shortcuts and having a plan to address them. So the next time you’re tempted to just “get it done,” take a moment to think long-term.
Fast doesn’t have to mean messy. Quality doesn’t have to mean slow. With the right practices, you can have both — and become the kind of engineer everyone wants on their team.
Have you found ways to balance speed and quality in your projects? I’d love to hear your strategies — drop them in the comments below!
Enjoyed this article? Follow me for more insights on becoming an Effective Engineer.