04 мар. 2026 г.·6 мин чтения

Стоимость хранения неиспользуемых функций: измерьте настоящий тормоз

Узнайте, как оценить стоимость хранения неиспользуемых функций: учитывайте тикеты поддержки, тестирование, задержки релизов и миграционную работу.

Стоимость хранения неиспользуемых функций: измерьте настоящий тормоз

Что на самом деле стоят «мертвые» функции

Функция может казаться дешёвой после релиза. Это может быть галочка в настройках, старый формат экспорта или процесс, которым пользуется лишь пара клиентов. Но она остаётся в продукте годами, и каждая новая правка вынуждена учитывать её.

Низкая активность не равна невысокой поддержке. Если 2% клиентов всё ещё пользуются опцией, команде всё равно нужно поддерживать её при редизайне экранов, обновлении API, изменении правил биллинга или исправлении багов рядом с ней. Маленькая опция может превратить простой релиз в долгий, потому что кто‑то всегда спросит: «Не сломали ли мы старый путь?»

Стоимость растёт тихо. Поддержка получает тикеты от людей, которым настройка уже не подходит. Инженеры держат дополнительные условия в коде. Команды продукта отвечают на один и тот же вопрос: зачем это тут?

Старая опция затрагивает больше, чем кажется. Она влияет на экран, логику, справку и шаблоны ответов, тесты для старого и нового поведения и на хранимые данные со старыми значениями.

Поэтому стоимость поддержки функции остаётся высокой, даже когда её используют единицы. Команда платит по чуть‑чуть, и этот «перетяг» легко не заметить. Десять лишних минут на планировании, лишний час на тестировании, ещё один ответ поддержки, одно правило миграции. Со временем это перестаёт быть мелочью.

Возьмём старую настройку уведомлений, которой пользуются считанные клиенты. При обновлении системы сообщений нельзя ограничиться проверкой нового потока: нужно проверить и старую настройку, сохранённые предпочтения, изменения аккаунта и обработку ошибок. В интерфейсе опция кажется крошечной. Работы за ней — нет.

Вот реальная цена хранения неиспользуемых функций. Они отнимают время у того, чем люди пользуются каждый день. Ущерб редко заметен в одном спринте — он проявляется в более медленных релизах, большем количестве краевых случаев и осторожности вокруг изменений, которые должны были быть простыми.

Где прячется стоимость

Функция может казаться дешёвой, когда ею пользуется мало людей. Реальная стоимость проявляется в мелких задачах по поддержке, QA, документации, обучению и продуктовой работе. Поэтому цену хранения редко используемых функций легко не заметить, пока команда не начнёт что‑то выпускать.

Поддержка обычно первая утечка. Даже если лишь небольшая группа использует старый формат экспорта или унаследованную настройку, они открывают тикеты, задают те же вопросы при настройке и нуждаются в помощи после обновлений. Один тикет сам по себе небольшой, но вместе они отвлекают внимание от проблем, затрагивающих всех.

То же происходит и вне очереди поддержки. Команда customer success держит старые скриншоты. Onboarding‑звонки становятся длиннее. Внутренние заметки собирают странные исключения. Одна устаревшая опция в демо — управляемо. Обучать каждого нового сотрудника пяти‑шести устаревшим опциям — это налог.

Стоимость тестирования растёт быстро, потому что каждая старая ветка добавляет случаи. Опция, меняющая поведение на одном экране, может влиять на импорты, права доступа, письма, отчёты и мобильные представления. QA в итоге проверяет комбинации, важные для единиц пользователей. Инженеры тоже чувствуют тормоз: простой рефакторинг начинается с вопроса «Не сломает ли это тот старый путь?»

Миграционный хвост растёт медленнее, но часто обходится дороже. Старые опции держат старые поля в базе, старые ответы API и правила в коде. Это может блокировать более чистую модель данных или заставлять команду поддерживать прослойки трансляции месяцами. Редизайн, который должен занять две недели, растягивается до шести, потому что никто не хочет трогать унаследованную ветку.

Функция не обязана часто ломаться, чтобы быть дорогой. Достаточно, чтобы она продолжала всплывать в поддержке, тестах и работах по изменениям долго после того, как её ценность исчезла.

Как измерять нагрузку поддержки

История тикетов скажет больше, чем мнения. Функция может выглядеть безобидно в интерфейсе, но inbox часто показывает реальную цену.

Начните с 6–12 месяцев тикетов, логов чата и заметок разговоров. Меньше — и один насыщенный месяц исказит картину. Больше — и продукт мог сильно измениться.

Создайте простой тег для функции и помечайте все связанные разговоры. Будьте строги. Считайте очевидные баг‑репорты, но также включайте вопросы по настройке, путаницу с биллингом, запросы на обучение и сообщения «как это работает?», если они возникают только из‑за наличия функции.

Просто считать тикеты недостаточно. Один пятиминутный ответ и один полудневный спасательный звонок — не одно и то же. Отслеживайте время каждой группы: время поддержки на ответы и донастройку, время продукта на объяснения и исключения, время инженеров на отладку или патчи и время customer success или sales для успокоения аккаунта.

Разделите работу на два ведра. Первое — единичные инциденты, например редкий баг после странного импорта. Второе — повторяющаяся путаница, когда люди не понимают функцию или постоянно попадают на один и тот же крайний случай. Повторяющаяся путаница важнее, потому что возвращается снова и снова.

Небольшая SaaS‑команда может сделать это в таблице. Если функция вызвала 18 тикетов за шесть месяцев, это ещё не звучит страшно. Но если поддержка потратила 6 часов, продукт 3, а инженеры 9, у вас уже 18 часов работы. При средней ставке $60/час это $1,080 за шесть месяцев, или $180 в месяц.

Эта цифра меняет разговор. Если лишь несколько клиентов всё ещё пользуются функцией, и большая часть работы — повторяющаяся путаница, это уже не споры о вкусе. Это ежемесячный счёт с именем.

Как измерять тестовую поверхность

Тестовая поверхность — это все места, где функция может сломаться, и все места, которые команда всё ещё проверяет из‑за её наличия. Многие команды считают только код — и пропускают реальную работу. Небольшая опция в UI может расходиться на QA, релизы, мониторинг и планы отката.

Начните с простой инвентаризации. Запишите каждый экран, правило и рабочий поток, которые затрагивает функция. Включите админские страницы, настройки, шаги онбординга, экспорты, правила прав, краевые случаи и любые потоки, которые меняются при включённой или выключенной опции.

Затем посчитайте проверки, связанные с этой инвентаризацией. Сюда входят ручные тесты, проверки в браузере и на мобильных, проверки прав, unit‑ и integration‑тесты, end‑to‑end покрытие, фикстуры и моки, smoke‑проверки перед деплоем и операционная работа: дашборды, алерты, логи и шаги отката.

Используйте простые числа. Считайте тест-кейсы. Считайте минуты. Считайте, сколько людей трогают функцию при обычном релизе. Если QA тратит 25 минут, инженеры просматривают три связанных теста, а релиз‑оунер запускает две дополнительные smoke‑проверки — запишите это. Мелочи быстро складываются.

Полезная привычка — сравнить две версии бок о бок. Сначала оцените усилия по релизу с функцией в продукте. Затем оцените усилия, если вы полностью её уберёте. Разница — это налог тестовой поверхности, который вы постоянно платите.

Функции не нужно иметь сотни тестов, чтобы быть дорогими. Иногда тормоз идёт от разветвлённого поведения: одна старая настройка может удвоить число путей, которые команда проверяет, потому что для каждого основного потока появляется вторая версия.

Не забывайте об откате. Если релиз провалился, может ли команда отключить функцию чисто, или нужен специальный скрипт, исправление данных или ручной шаг поддержки? Если откат усложняется, тестовая поверхность шире, чем кажется.

Если нужен один показатель, используйте этот:

Test surface score = manual checks + automated tests + release-only checks + operational checks

Это не идеально, но даёт конкретное число для сравнения с более простым продуктом.

Как измерять миграционный налог

Проверка нагрузки поддержки
Измерьте, какие редко используемые функции создают лишнюю работу для поддержки.

Миграционный налог проявляется, когда старая функция усложняет каждое изменение. Команды часто считают только код и упускают работу с данными, коммуникацией с клиентами и настройкой аккаунтов. Эта разница делает стоимость меньше, чем она есть.

Начните с модели данных. Перечислите каждое поле, таблицу, настройку, статус и отчёт, которые затрагивает функция. Затем отметьте, что происходит с каждым элементом при редизайне, чистке базы или переносе платформы: оставить, объединить, переименовать, архивировать или удалить.

Отчёты важны больше, чем думают многие. Функция может выглядеть небольшой в приложении, но питать дашборды, финансовые выгрузки, админ‑экраны и отчёты клиентов. Если одна старая опция меняет пять отчётов, миграционная работа быстро растёт.

Посчитайте все места пересечения

Старые функции редко живут в одном экране. Проверьте импорты, экспорты, API, вебхуки и внешние интеграции, которые читают или пишут связанные данные. Если клиенты подтягивают эти данные в другой инструмент, удаление замедляется из‑за правил маппинга, запасного поведения и ответов поддержки.

Простой аудит должен учесть поля и отчёты, форматы импорта/экспорта, внешние интеграции, внутренние автоматики, уведомления клиентам, справку, обновления обучения и изменения аккаунтов вроде новых дефолтов или прав.

Затем разделите работу на два ведра. Одноразовая миграционная работа включает скрипты, маппинг полей, правки отчётов, письма клиентам и правки аккаунтов. Оngoing‑нагрузка включает дополнительные тест‑кейсы, тикеты поддержки, краевые случаи и ограничения будущих редизайнов.

Это разделение важно. Одноразовая работа болезненна, но заканчивается. Постоянный налог виден в каждом релизе.

Дайте этому число

Сначала используйте часы. Оцените, сколько займёт каждая задача у продукта, инженеров, поддержки и customer success. Если нужен простой счёт, используйте:

migration drag = one-time change hours + 12 months of ongoing support and maintenance hours

Для маленького SaaS‑продукта старая опция экспорта может потребовать 6 часов на маппинг данных, 4 часа на обновление отчётов, 3 часа на письма и справку и 2 часа на правки аккаунтов. Это 15 часов разово. Если та же опция добавляет 2 часа поддержки и 1 час тестирования в месяц, годовой налог достигает 51 часа.

Эта цифра даёт более чистое решение об удалении, чем одни только метрики использования. Функция с низкой активностью и высоким миграционным налогом вряд ли заслуживает защищённого места в следующем редизайне.

Простой пример из небольшого SaaS‑продукта

Небольшой SaaS для полевых команд предлагает три формата экспорта: CSV, PDF и старый XML, сделанный под интеграцию одного клиента годы назад. XML всё ещё в меню, поэтому команда считает его безобидным дополнением. Именно так старые функции и живут.

Данные показывают другое. В продукте 1,200 активных аккаунтов, но за последние 90 дней XML использовали только 9. Пять из них — внутренние тесты. Двое использовали формат один раз для проверки биллинга. Только два аккаунта применяли его в рабочем процессе.

Поддержка выглядит занятым немного, пока кто‑то не посчитает. В среднем три XML‑тикета в месяц, каждый по 20–30 минут. Людям приходится доставать старые заметки, смотреть странные имена полей и спрашивать инженеров, ожидается ли пустой тег или это баг. Это около 75 минут в месяц на формат, которым почти никто не пользуется.

QA тоже платит. Каждый релиз требует дополнительного регрессионного прохода для XML — около 45 минут в месяц в рутине, плюс ещё 2–3 часа при изменениях в полях отчётов. Команда держит хрупкую тестовую фикстуру для этого формата, и она падает чаще, чем новые тесты экспорта.

Большее проявляется при переписывании отчётности. Продукт хочет упростить модель отчётов, объединить дублирующие поля и поправить нейминги. XML блокирует работу, потому что зависит от старых имён полей и вложенности. Инженерам нужны адаптеры, заметки миграции и параллельные проверки вывода. Редизайн, который должен был занять две недели, тянется почти три.

Это цена хранения неиспользуемых функций в явном виде. Функция дорога не потому, что код большой, а потому что она берёт плату понемногу каждый месяц, а затем бьёт сильнее, когда продукт нужно двигать.

Разумный ход здесь — заменить, а затем удалить. Сохраните XML для двух клиентов, которым он нужен, предложите им маппинг в CSV или простой кастомный фид, назначьте дату стекания и уберите старую опцию из основного продукта. Хранить её вечно бессмысленно. Удалять завтра — опрометчиво. Короткий путь миграции — золотая середина.

Ошибки команд, которые сохраняют старые функции

Уберите старые функции
Удаляйте старые опции, которые замедляют релизы и путают клиентов.

Команды редко держат старые функции потому, что цифры однозначны. Их держат, потому что кто‑то в компании эмоционально к ним привязан. Основатель вспомнил один sales‑звонок. Лид поддержки боится жалоб. Инженер говорит: «Почти не стоит ничего держать.»

Последняя фраза делает много вреда. Команды часто считают только время на код и упускают остальную стоимость поддержки. Старые опции создают дополнительные тикеты, больше краевых случаев в тестах, больше документов для обновления и больше осторожности при редизайне. Функция, которой никто не пользуется, всё равно может тормозить каждый релиз.

Ещё одна ошибка — доверять громким голосам вместо данных использования. Внутренние команды слышат просьбу дважды и принимают это за устойчивый спрос. Потом смотрят на числа и видят, что только крохотная группа использовала функцию, и многие попробовали её один раз и не вернулись. Один клиент, просящий особенную фичу, не превращает её в вечную часть продукта.

Feature flags (флаги функций) сами по себе создают беспорядок, если о них забывают после эксперимента. То, что начиналось как временная ветка, становится постоянным мусором. Новым разработчикам нужно понимать оба пути. QA тестирует оба варианта. Поддержка помнит, кто видит что. Флаг перестаёт быть страховкой и превращается в технический долг.

Удаление тоже можно сделать плохо. Некоторые команды наконец‑то режут функцию без уведомлений, замены или плана миграции. Это вызывает гнев, которого можно было избежать. Даже при низкой активности тем немногим, кто ею пользовался, нужен путь вперёд.

Более безопасный подход прост: смотрите на реальное использование со временем, а не на анекдоты; считайте работу поддержки и тестирования, а не только код; ставьте даты завершения для флагов; отделяйте единичные запросы от широкого спроса; планируйте удаление с уведомлением и запасным вариантом.

Команды обычно замечают цену поздно, когда каждая мелкая правка начинает тянуться дольше, чем должна.

Быстрая проверка перед тем, как оставить или вырезать

Сократите лишнюю работу QA
Найдите старые ветки и настройки, которые добавляют нагрузку на тестирование.

Хорошее решение об удалении начинается с нескольких простых вопросов. Вам не нужен долгий спор — нужно достаточно доказательств, чтобы понять, приносит ли функция пользу.

Начните с недавнего использования. Если лишь небольшое число пользователей касалось её за последние 90 дней, это не обязательно означает немедленное удаление, но смещает бремя доказательства. Редко используемая опция может остаться, если она поддерживает серьёзную потребность, юридическое требование или договорное обещание. Если таких причин нет, стоимость хранения обычно растёт быстрее, чем команды ожидают.

Дальше — налог релиза. Сколько дополнительного времени QA, проверки багов, работы с документацией, ответов поддержки и осторожности при деплое добавляет эта функция при каждом изменении продукта? Многие команды недооценивают это, потому что работа распределена по отделам.

Затем спросите, блокирует ли функция что‑то большее. Старые опции часто задерживают редизайны, переносы бэкенда, изменения прайсинга или очистку модели данных. Когда это происходит, функция уже не маленькая.

Проверьте, может ли более простой вариант выполнить ту же работу для большинства пользователей. Если да, старая версия, вероятно, балласт. Наконец, перечислите, кого нужно предупредить, кому дать экспорт или запасной путь, чтобы удаление не вызвало паники или оттока.

Если всё ещё сомневаетесь, попробуйте мягкий выход: скрыть опцию для новых пользователей, заранее предупредить текущих и предложить простой путь к замене. Это даст дополнительный сигнал перед окончательным удалением и сделает очистку спокойной, а не хаотичной.

Что делать дальше

Не начинайте с масштабного проекта по очистке. Выберите одну малоиспользуемую функцию на этой неделе и измерьте её. Посчитайте тикеты поддержки, тесты, документы и миграционную работу, которые она добавляет при изменениях продукта.

Это небольшое упражнение обычно меняет разговор. Команды перестают спорить по привычке и начинают смотреть на цифры. Вам не нужны идеальные данные, чтобы увидеть стоимость хранения неиспользуемых функций. Даже грубая оценка часто показывает, что крошечная опция создаёт реальное сопротивление.

Напишите короткую записку с решением, пока факты свежи. Держите её короткой, чтобы люди потом прочитали. Чаще всего исход — одно из четырёх: оставить (если использование оправдывает работу), слить/объединить (если есть дубли), заменить (если нужен результат, но не текущая реализация) или удалить (если использование низкое, а поддержка съедает время).

Положите заметку туда, где команда уже работает: бэклог или продуктовая документация. Назначьте одного владельца. Если решение никому не принадлежит, старые опции будут висеть годами.

Назначьте дату проверки: 30, 60 или 90 дней обычно хватает. Дата важна: команды редко возвращаются к старым решениям, если календарь этого не требует.

Лучше перестать спрашивать «Может, оставим на всякий случай?» и начать спрашивать «Сколько это нам стоит каждый месяц?». Это более продуктивный вопрос для очистки продукта.

Если команда хочет внешний взгляд на такую очистку, Oleg Sotnikov at oleg.is может оценить архитектуру, посмотреть нагрузку поддержки и помочь решить, что оставить, объединить, заменить или удалить.

Часто задаваемые вопросы

Why does a barely used feature still cost so much?

Потому что команда продолжает «платить» за неё по частям. Поддержка отвечает на вопросы, QA проверяет старые ветки, инженеры держат дополнительные условия в коде, а продуктовые люди учитывают старые данные. Низкая активность скрывает затраты, но не устраняет их.

How do I know if a feature is really dead?

Посмотрите на недавнее использование и реальную зависимость. Если за последние 90 дней очень мало аккаунтов обращались к функции, и большая часть этих обращений — внутренние тесты или одноразовые проверки, скорее всего это кандидат на очистку. Перед удалением проверьте контрактные обязательства, юридические требования или ключевые рабочие процессы клиентов.

What support work should I count?

Считайте не только баг-репорты. Включите вопросы по настройке, путаницу с биллингом, запросы на обучение, аварийные звонки и любое время на доработки от поддержки, продукта, инженерии или customer success. Часы важнее простого числа тикетов — один долгий инцидент может перевесить много быстрых ответов.

How far back should I look at support history?

Берите историю за 6–12 месяцев: тикеты, чаты и заметки разговоров. Такой промежуток сглаживает один шумный месяц и остаётся актуальным для текущего продукта. Короткое окно вводит в заблуждение, а очень старые данные могут описывать уже изменившийся продукт.

What does test surface mean?

Тестовая поверхность — это все места, где функция может сломаться и всё, что команда продолжает проверять из‑за её наличия. Сюда входят экраны, правила, ручное QA, автоматические тесты, smoke‑проверки, тревоги, логи и шаги отката. Небольшая опция может породить много проверок, если она меняет поведение в нескольких потоках.

How do I measure test surface in a practical way?

Сравните один и тот же релиз двумя версиями: с функцией и без неё. Выпишите тест-кейсы, минуты работы, вовлечённых людей и дополнительные smoke или шаги отката. Разница между этими двумя оценками показывает, сколько функция вам «стоит» в плане тестирования.

What counts as migration drag?

Начните с данных и всех границ, через которые проходит функция. Посчитайте поля, отчёты, импорты, экспорты, API, вебхуки, документацию, уведомления клиентам и изменения аккаунтов. Затем сложите одноразовую работу по изменению с годом постоянной поддержки и сопровождения.

When should I keep a low-use feature?

Оставляйте её, если она поддерживает реальную потребность, превышающую затраты: контрактные обещания, юридические требования или важный рабочий процесс платящих клиентов. Если большинство кейсов покрывает более простой вариант, а старая версия тормозит релизы, хранить её обычно не имеет смысла.

What is a soft exit for a feature?

Мягкий выход — это когда вы перестаёте относиться к функции как к полноценной части продукта до окончательного удаления. Скрываете её от новых пользователей, заранее предупреждаете текущих, предлагаете замену или запасной путь и назначаете дату выключения. Это даёт дополнительный сигнал и избегает резких конфликтов при удалении.

What should I do first if I want to clean this up?

Выберите одну редко используемую функцию на этой неделе и измерьте её: время поддержки, покрытие тестами, работу с документацией и миграционную нагрузку. Затем составьте короткую заметку с решением: оставить, слить, заменить или удалить. Небольшой шаг обычно переводит обсуждение из эмоций в цифры.