There''s a conversation I have several times a year with new clients. They show up saying "I think my application needs a complete rewrite", they describe the symptoms, and usually the honest answer is no, you don''t need to tear it all down, but there are three or four concrete things bleeding money that nobody is looking at. Other times, the conversation goes the other way — the client thinks their app "works reasonably" and turns out it''s screaming for a refactor.
Refactor doesn''t mean rewrite from scratch. Rewriting from scratch is almost always a bad idea, and when it isn''t, it''s almost always for non-technical reasons. Refactor means intervening in specific parts of the code, infrastructure or process so the application stops costing you more than it brings in. I''m going to give you seven objective signs that, when they appear, usually mean it''s time. And at the end, three signs that look serious but usually aren''t.
1. Deployments take over 30 minutes or feel scary
A healthy deployment in 2026 takes between 3 and 10 minutes for a medium-sized app, launches automatically from a commit to a protected branch, and nobody has to babysit anything. If yours takes longer, needs manual intervention, or the team crosses their fingers every time you deploy on a Friday, you''ve got a serious process problem.
Slow deployments aren''t just a nuisance: they''re the visible symptom of a process that discourages shipping small, frequent changes. When shipping hurts, the team batches changes to avoid the pain twice. When batches grow, each deployment is bigger, riskier and more painful. It''s a spiral that ends with monthly releases that generate three production bugs each time. Breaking it takes a few weeks of CI/CD work and the team velocity improvement is immediate.
2. More than five production bugs per month
A mature application in stable maintenance should generate between zero and two production incidents per month. If you''ve been running months with five or more serious bugs each month — incidents that affect real users, not log warnings — your application is asking for intervention. It''s probably not "badly written". Something in the development, testing or deployment process is letting bugs through to the client.
The first thing I check in these cases is automated test coverage on critical paths, not on the total. If your app processes payments, are there end-to-end payment flow tests? If it generates invoices, are there tax calculation tests? Teams often focus on having "high coverage" overall and neglect flows where a bug costs real money to the client or their business.
3. Zero automated tests (or "tests" nobody runs)
Not having tests isn''t necessarily serious in a small app that barely changes. But once the application grows, has multiple developers touching it, or lives over two years, lack of automated tests becomes a huge brake. Every change becomes risky, every refactor is postponed, and the code ossifies.
The worst variant is the team that has written tests, but CI ignores them, or they''ve been failing for months, or nobody runs them before merging. That''s worse than having none: it gives you a false sense of security while bugs keep slipping through. If your pipeline has had "failing tests we''ll fix soon" for months, it''s been months without functional tests.
4. Framework is unsupported or very outdated
.NET Framework 4.8 still works, but Microsoft no longer adds new features and only releases security patches. .NET 6 lost support in November 2024. .NET 8 will lose it in November 2026. If your app is on unsupported versions, it''s not going to explode tomorrow, but each month that passes you''re accumulating debt and exposing yourself to unpatched vulnerabilities.
Updating the framework isn''t as expensive as people think, especially if the code isn''t too twisted. The hard part is usually old dependencies no longer maintained that need replacing, and integration with legacy systems assuming specific versions. A framework and dependency version audit takes one or two days and tells you exactly what catching up costs.
5. The team says "you can''t touch X"
When a team developer tells you "that part can''t be touched, it''s very delicate", or "if we modify that everything else breaks", or "Joe wrote it five years ago and he''s gone", you''re hearing untouchable code. And untouchable code is code that each year is more likely to explode when you least expect it.
This typically happens with central modules — commission calculation, accounting report generation, pricing logic — written in a hurry, without tests, and nobody wanted to rewrite because "it works". When the inevitable change comes, they fix it with a patch on top of a patch, and debt grows. Identifying those modules, writing tests that document current behavior, and then refactoring step by step is one of the most profitable jobs a senior freelancer can do. I''ve seen this recover control of a codebase in six or eight weeks in projects that had been blocked for two years.
6. Response times worsen year over year
If your application takes twice as long to load today as it did two years ago, without concurrent users having gone up, something is wrong and it''s not the cloud. It''s very likely the database: queries that scale poorly as data grows, indexes that became obsolete, or the classic N+1 problem multiplying with volume.
These problems are cheap to detect (a day of profiling with MiniProfiler or equivalent) and usually cheap to fix. But they need to be done in time. When a client waits eight seconds for a screen to load, they don''t wait, they leave. I''ve seen apps that had a single misconfigured index problem, and adding it brought response times from 12 seconds to 400 milliseconds. But until someone really sits down to look at it, it doesn''t surface.
7. Cloud cost goes up without traffic going up
If your Azure or AWS bill rises each quarter but users and data don''t, what''s happening is your app is increasingly inefficient. More unclosed database connections, more memory not being released, more unnecessary calls to external services. And you pay that in infrastructure without getting anything in return.
A well-done cloud cost audit usually saves between 20 and 40 % of the monthly bill with changes that don''t affect the end user. ROI is immediate: if your bill is €800 a month and we bring it down to €500, the €300 monthly pays for the work in a few weeks. It''s one of the best value-for-money services in the market, in a good way: it costs little and returns much.
The 3 false signs that confuse many clients
Not everything that looks bad is bad. These three are the most common "false alarms" clients bring thinking their app is in crisis when actually they''re fine.
Having many lines of code
The absolute number of lines means nothing by itself. A 50,000-line app can be perfectly healthy, and a 5,000-line one can be hell if poorly structured. What matters is cyclomatic complexity per method, module cohesion, and whether the code is understandable to someone new to the project. SonarQube gives you an honest picture of this in a day.
Seeing warnings in logs
Logs full of warnings are scary, but most are usually noise: third-party library warnings, deprecation notices about future versions, informational messages categorized as warning by mistake. What matters are errors and exceptions reaching production. If those are under control, warnings can wait.
"The code is old"
That code was written in 2018 doesn''t make it bad. If it works, is tested, is maintained, and doesn''t have broken dependencies, 2018 code is perfectly valid in 2026. What ages badly is code without tests, without documentation, with abandoned dependencies — and that can happen just as easily with code written yesterday.
What to do if you see three or more of these signs
If you''ve recognized three or more of the seven real signs, the most sensible thing is to do a technical audit before considering any rewrite. The audit gives you a map: what''s bleeding, what''s stable, what to touch first, what to leave for later, and what to ignore.
Without that map, "rewrite everything" budgets are huge and almost always end badly — because rewriting an entire app while the current one keeps serving is a monstrous project. With the map, you usually discover that two months of well-directed intervention solves 80 % of the problems. And only if the app is so rotten that maintaining it costs more than replacing it, then a rewrite makes sense — but then it''s a decision with data, not panic.