Cost of keeping unused features: measure the real drag
Learn how to estimate the cost of keeping unused features by tracking support tickets, test work, release delays, and migration effort.

What dead features really cost
A feature can look cheap once it ships. It might be a checkbox in settings, an old export format, or a workflow only a few customers still use. Then it stays in the product for years, and every new change has to work around it.
Low usage does not mean low maintenance. If 2% of customers still touch an option, the team still has to keep it working when they redesign screens, update APIs, change billing rules, or fix bugs in nearby code. A tiny option can turn a simple release into a longer one because someone always has to ask, "Did we break the old path?"
The cost spreads quietly. Support gets tickets from people who find a setting that no longer fits the rest of the product. Engineers keep extra conditions in the code. Product teams keep answering the same question: why is this still here?
An old option also reaches farther than it first appears. It touches the screen where users see it, the logic behind it, the help docs and canned replies around it, the tests for both old and new behavior, and the stored data that still carries old values.
That is why feature maintenance cost stays high even when usage stays low. The team pays in small pieces, so the drag is easy to miss. Ten extra minutes in planning, an extra hour in testing, one more support reply, one more migration rule. Over months, that stops being small.
Take an old notification setting that only a few customers use. When the team updates the messaging system, they cannot just test the new flow. They also have to check the legacy setting, old saved preferences, account changes, and error handling. The setting looks tiny in the interface. The work behind it is not.
This is the real cost of keeping unused features. They pull time away from the parts of the product people use every day. The damage rarely looks dramatic in one sprint. It shows up as slower releases, more edge cases, and more caution around changes that should have been simple.
Where the cost hides
A feature can look cheap when few people touch it. The real cost shows up in small jobs spread across support, QA, docs, onboarding, and product work. That is why the cost of keeping unused features is easy to miss until a team tries to ship something new.
Support is usually the first leak. Even if only a small group still uses an old export format or legacy setting, they still open tickets when it breaks, ask the same setup questions, and need help after updates. Each ticket looks minor on its own. Together, they keep pulling attention away from problems that affect everyone.
The same thing happens outside the support queue. Customer success teams keep old screenshots in play. Onboarding calls get longer. Internal notes collect weird exceptions. One outdated option in a demo is manageable. Training every new teammate on five or six outdated options is a tax.
Testing cost grows fast because every old branch adds more cases. A setting that changes behavior in one screen can affect imports, permissions, emails, reports, and mobile views. QA ends up checking combinations that matter to very few users. Engineers feel the same drag, because even a simple refactor starts with, "Will this break that old path?"
Migration drag is slower, but often more expensive. Old options keep old fields in the database, old API responses, and old rules in the code. That can block a cleaner data model or force the team to carry translation layers for months. A redesign that should take two weeks turns into six because nobody wants to touch the legacy branch.
A feature does not need to fail often to be expensive. It only needs to keep showing up in support, testing, and change work long after its value is gone.
How to measure support load
Support history tells you more than opinions ever will. A feature may look harmless in the product, but the inbox often shows the real cost.
Start with 6 to 12 months of tickets, chat logs, and call notes. Shorter than that, and one busy month can distort the result. Longer than that, and the product may have changed too much to compare fairly.
Create a simple tag for the feature and mark every related conversation. Be strict. Count obvious bug reports, but also include setup questions, billing confusion, training requests, and "how does this work?" messages if they exist only because the feature exists.
A raw ticket count is not enough. One five-minute answer and one half-day rescue call should not carry the same weight. Track the time spent by each group involved: support time to answer and follow up, product time to explain behavior or make exceptions, engineering time to debug or patch, and any customer success or sales time spent calming an unhappy account.
Then split the work into two buckets. First, one-off issues, such as a rare bug after a strange import. Second, repeat confusion that shows people do not understand the feature or keep hitting the same edge case. Repeat confusion matters more because it keeps coming back month after month.
A small SaaS team can do this in a spreadsheet. If a feature caused 18 tickets in six months, that may not sound bad. But if support spent 6 hours, product spent 3, and engineers spent 9, you already have 18 hours of work. At a blended rate of $60 per hour, that is $1,080 over six months, or $180 per month.
That number changes the conversation. If only a few customers still touch the feature, and most of the work comes from repeat confusion, you are no longer debating taste. You are looking at a monthly bill with a name on it.
How to measure test surface
Test surface is every place a feature can break, and every place your team still has to check because the feature exists. Many teams count only the code. That misses the real work. A small option in the UI can spread into QA, releases, monitoring, and rollback plans.
Start with a plain inventory. Write down every screen, rule, and workflow the feature touches. Include admin pages, settings, onboarding steps, exports, permission rules, edge cases, and any flow that changes when the feature is on or off.
Then count the checks tied to that inventory. That includes manual QA paths, browser and mobile checks, permission checks, unit and integration tests, end-to-end coverage, fixtures and mocks, smoke tests people still run before deploy, and operational work such as dashboards, alerts, logs, and rollback steps.
Use simple numbers. Count test cases. Count minutes. Count how many people touch the feature in a normal release. If QA spends 25 minutes on it, engineering reviews three related tests, and the release owner runs two extra smoke checks, write that down. Small pieces add up fast.
A useful habit is to compare two versions side by side. First, estimate the release effort with the feature still in the product. Second, estimate the effort if you remove it completely. The gap is the test surface tax you keep paying.
A feature does not need hundreds of tests to be expensive. Sometimes the drag comes from branching behavior. One old setting can double the number of paths your team checks because every main workflow now has a second version.
Do not forget rollback. If a release fails, can the team disable the feature cleanly, or do they need a special script, data fix, or manual support step? If rollback gets harder, the feature has a wider test surface than it first appears.
If you want one score, use this:
Test surface score = manual checks + automated tests + release-only checks + operational checks
It is not perfect, but it gives you something concrete to compare against a simpler product.
How to measure migration drag
Migration drag shows up when an old feature makes every change harder. Teams often count the code work and miss the extra work around data, customer communication, and account setup. That gap can make the cost look smaller than it is.
Start with the data model. List every field, table, setting, status, and report the feature touches. Then mark what happens to each item during a redesign, database cleanup, or platform move: keep it, merge it, rename it, archive it, or delete it.
Reports matter more than most teams expect. A feature may look small in the app, but it can feed dashboards, finance exports, admin screens, and customer reports. If one old option changes five reports, the migration work grows quickly.
Count every place the feature crosses the boundary
Old features rarely stay inside one screen. Check every import, export, API, webhook, and outside integration that reads or writes the related data. If customers pull that data into another tool, removal gets slower because you need mapping rules, fallback behavior, and support answers.
A simple audit should count affected fields and reports, import and export formats, outside integrations, internal automations, customer notices, help docs, training updates, and account changes such as new defaults or permission edits.
Then split the work into two buckets. One-time migration work includes scripts, field mapping, report edits, customer notices, and account changes. Ongoing drag includes extra test cases, support tickets, edge cases, and future redesign limits.
That split matters. One-time work can feel painful, but it ends. Ongoing drag shows up in every release.
Put a number on it
Use hours first. Estimate how long each task will take across product, engineering, support, and customer success. If you want a simple score, use this:
migration drag = one-time change hours + 12 months of ongoing support and maintenance hours
For a small SaaS product, an old export option might need 6 hours for data mapping, 4 hours for report updates, 3 hours for customer emails and help docs, and 2 hours for account fixes. That is 15 hours once. If the same option also causes 2 support hours and 1 testing hour each month, the yearly drag reaches 51 hours.
That number gives you a cleaner feature removal decision than usage alone. A feature with low use and high migration drag usually does not deserve a protected spot in the next redesign.
A simple example from a small SaaS product
A small SaaS product for field service teams offers three export options: CSV, PDF, and an old XML export built for one customer integration years ago. The XML option still sits in the menu, so the team keeps treating it like a harmless extra. That is how old features linger.
Usage data tells a different story. The product has 1,200 active accounts, but only 9 touched the XML export in the last 90 days. Five of those were internal test runs. Two customers used it once for a billing check. Only two accounts used it as part of their normal workflow.
The support work looks small until someone counts it. Support gets about three XML tickets a month, and each one takes 20 to 30 minutes. People have to dig up old notes, inspect strange field names, and ask engineering if a blank tag is expected or broken. That is about 75 minutes a month for a feature almost nobody uses.
QA pays for it too. Every release needs one extra regression pass for the XML export. That adds about 45 minutes a month in routine checks, plus another 2 to 3 hours whenever reporting fields change. The team also keeps a brittle test fixture just for this format, and it fails more often than newer export tests.
The bigger cost appears during a reporting rewrite. Product wants to simplify the report model, merge duplicate fields, and clean up naming. The XML format blocks that work because it depends on old field names and old nesting rules. Engineers now need adapter logic, extra migration notes, and side-by-side output checks. A rewrite that should take two weeks stretches closer to three.
This is the cost of keeping unused features in plain view. The feature is not expensive because the code is large. It is expensive because it keeps charging a little every month, then charges a lot when the product needs to move.
The sensible move here is replace, then remove. Keep the XML export for the two customers who still need it, give them a CSV mapping or a simple custom feed, set a sunset date, and take the old option out of the main product. Keeping it forever makes no sense. Removing it tomorrow would be careless. A short migration path is the middle ground.
Mistakes teams make when they keep old features
Teams rarely keep old features because the numbers are clear. They keep them because someone inside the company feels strongly about them. A founder remembers one sales call. A support lead worries about complaints. An engineer says, "It barely costs anything to keep."
That last line causes a lot of damage. Teams often count only coding time and miss the rest of the feature maintenance cost. Old options create extra tickets, more edge cases in testing, more docs to update, and more hesitation during redesigns. A feature that nobody touches can still slow every release.
Another common mistake is trusting loud opinions over usage data. Internal teams hear a request twice and assume steady demand. Then they check the numbers and find that only a tiny group used the feature, and many of them tried it once and never came back. One customer asking for something does not make it part of the product forever. Sometimes it is just one customer asking for special treatment.
Feature flags create their own mess when teams forget to clean them up after an experiment. What started as a temporary branch becomes permanent product clutter. New developers need time to understand both paths. QA has to test both paths. Support has to remember which customers see which version. The flag stops being a safety tool and turns into product debt.
Removal can go wrong too. Some teams finally cut a dead feature, but they do it with no notice, no replacement, and no migration plan. That creates anger that could have been avoided. Even if the feature had low usage, the few people who relied on it still need a path forward.
A safer approach is simple: check real usage over time instead of anecdotes, count support and testing work instead of code alone, set end dates for old feature flags, separate one-off requests from broad demand, and plan removal with notice and a fallback.
Teams usually notice the cost late, when every small change starts to feel heavier than it should.
Quick checks before you keep or cut it
A good feature removal decision starts with a few plain questions. You do not need a long debate first. You need enough evidence to see whether the feature still earns its place.
Start with recent use. If only a small number of users touched it in the last 90 days, that does not force removal on its own, but it changes the burden of proof. A rarely used option can still stay if it supports a serious customer need, a legal requirement, or a contract promise. If it has no such reason, the cost of keeping unused features usually grows faster than teams expect.
Then look at the release tax. How much QA time, bug checking, documentation work, support follow-up, and deployment caution does this feature add every time the product changes? Many teams underestimate this because the work is split across departments.
Next, ask whether the feature blocks something bigger. Old options often hold up redesigns, backend moves, pricing changes, or cleanup of the data model. When that happens, the feature is no longer small.
Also check whether a simpler option can do the same job for most people. If yes, the older version may be dead weight. Finally, list who will need notice, export help, or a fallback so removal does not create panic or churn.
If you still feel unsure, try a soft exit. Hide the option for new users, warn current users early, and offer a simple path to the replacement. That gives you one more signal before you fully remove it, and it keeps product cleanup calm instead of messy.
What to do next
Do not start with a full cleanup project. Pick one low-use feature this week and measure it. Count the support questions it creates, the tests it touches, the docs it needs, and the migration work it adds when the product changes.
That small exercise usually changes the conversation. Teams stop arguing from habit and start looking at numbers. You do not need perfect data to see the cost of keeping unused features. Even a rough count often shows that a tiny option creates real drag.
Write a short decision note while the facts are fresh. Keep it short enough that people will read it later. In most cases, the outcome is one of four things: keep it if people still use it enough to justify the extra work, merge it if it overlaps with another option, replace it if users need the outcome but not the current version, or remove it if usage is low and the upkeep keeps stealing time.
Put that note where the team already works, such as the backlog or product docs. Name one owner. If nobody owns the decision, old options tend to sit there for years.
Set a review date before you move on. Thirty, sixty, or ninety days is usually enough. The date matters because product teams rarely revisit old choices unless the calendar forces the issue.
A better habit is to stop asking, "Can we keep it just in case?" and start asking, "What does it cost us every month?" That is a better product cleanup question.
If your team wants an outside read on this kind of cleanup, Oleg Sotnikov at oleg.is can review the product architecture behind these decisions, look at support load, and help you decide what to keep, merge, replace, or remove.
Frequently Asked Questions
Why does a barely used feature still cost so much?
Because the team keeps paying around it. Support answers questions, QA checks old branches, engineers carry extra conditions, and product people work around old data. Low usage hides the cost, but it does not remove it.
How do I know if a feature is really dead?
Look at recent use and real dependence. If very few accounts touched it in the last 90 days, and most of that use came from testing or one-off checks, you likely have a cleanup candidate. Before you cut it, check for contract, legal, or customer workflow reasons to keep it.
What support work should I count?
Count more than bug reports. Include setup questions, billing confusion, training requests, rescue calls, and any follow-up time from support, product, engineering, or customer success. Hours matter more than raw ticket count because one long incident can outweigh several quick replies.
How far back should I look at support history?
Use 6 to 12 months of tickets, chats, and call notes. That window smooths out one noisy month and still reflects the current product. Shorter windows can mislead you, and much older data often describes a product that has already changed.
What does test surface mean?
Test surface is every place the feature can break and every place your team still checks because it exists. That includes screens, rules, manual QA, automated tests, smoke checks, alerts, logs, and rollback work. A small option can create a lot of checking when it changes behavior in more than one flow.
How do I measure test surface in a practical way?
Compare the same release in two versions: one with the feature still there and one with it fully removed. Write down test cases, minutes spent, people involved, and any extra smoke or rollback checks. The gap between those two versions shows what the feature keeps costing you.
What counts as migration drag?
Start with the data and every boundary it crosses. Count fields, reports, imports, exports, APIs, webhooks, docs, customer notices, and account changes tied to the feature. Then add the one-time change hours to a year of ongoing support and maintenance hours.
When should I keep a low-use feature?
Keep it when it supports a real need that outweighs the drag. Contract promises, legal requirements, or a workflow that still matters to paying customers can justify it. If a simpler option covers most cases and the old one keeps slowing releases, keeping it rarely makes sense.
What is a soft exit for a feature?
A soft exit means you stop treating the feature like a normal part of the product before you fully remove it. Hide it from new users, warn current users early, offer a replacement or fallback, and set a clear sunset date. That gives you cleaner data and avoids a messy surprise.
What should I do first if I want to clean this up?
Pick one low-use feature this week and measure it. Count support time, test time, docs work, and migration work, then write a short keep, merge, replace, or remove note with one owner and a review date. That small step usually turns a vague argument into a clear decision.