Разработчик потратил две недели на замену REST API на tRPC во внутреннем инструменте.
Почему этот переход имел значение
Старый стек заставлял нас поддерживать DTO, валидатор и отдельный набор типов TypeScript для фронтенда. Стоило переименовать поле на бэкенде, как API всё равно возвращал 200, UI продолжал отрисовываться, а баг проявлялся только в виде значений «undefined». Клиент заметил проблему раньше, чем кто-либо из команды. REST-контракты скрывали проблему, а лишние файлы создавали нагрузку на поддержку, которая никогда не окупалась.
Как выглядела настройка REST
- OpenAPI spec — статический файл, который описывал эндпоинты, но никогда не служил «источником истины» (source of truth).
- Этап генерации Client SDK — задача в CI, которая создавала JavaScript-обертку.
- Postman collection — общий артефакт для тестирования, которым никто не пользовался.
- Ручные TypeScript interfaces — написанные вручную типы, которые нужно было синхронизировать с сервером.
Каждое изменение API затрагивало как минимум три из этих артефактов, плюс валидатор и любые последующие вызовы fetch. Процесс был медленным и подверженным ошибкам.
Как tRPC сократил кодовую базу
tRPC избавляет от необходимости иметь отдельный файл контракта. Сервер экспортирует тип роутера, а клиент импортирует тот же самый тип. Переименуйте поле на бэкенде, и редактор мгновенно подсветит несоответствие — не нужно ни запускать код, ни ждать ошибки запроса. Разработчик удалил:
- Файл OpenAPI spec.
- Этап генерации client SDK.
- Неиспользуемую Postman collection.
- Папку с ручными TypeScript interfaces.
Репозиторий стал чище, а обратная связь стала приходить во время разработки, а не после деплоя.
Ограничения tRPC
tRPC работает только тогда, когда обе стороны используют TypeScript. Он не подходит, если:
- Мобильная команда использует Swift или Kotlin.
- API должен использоваться внешними партнерами.
- Вам нужен публичный, независимый от языка интерфейс.
Что на самом деле потребовалось для миграции
Двухнедельная работа заключалась не только в копировании и вставке. Разработчику пришлось:
- Переписать каждый вызов
fetch, чтобы использовать клиентские функции tRPC. - Скорректировать логику обработки ошибок.
- Обновить UI-компоненты, которые полагались на состояния загрузки (loading) и повторных попыток (retry), привязанные к «сырым» HTTP-ответам.
Вопросы, которые стоит задать перед переходом
- Используют ли фронтенд и бэкенд TypeScript? Без общей системы типов tRPC теряет свое главное преимущество.
- Отвечает ли одна и та же команда за обе стороны? Разрыв в зонах ответственности может снова привести к расхождению контрактов.
- Вы исправляете конкретный баг или следуете тренду? Рост продуктивности реален, но переход должен решать существующую проблему.
Гибридный подход для 2025 года
Многие команды находят оптимальный баланс, используя оба стека:
- tRPC для внутренних слоев приложения, где кодовая база полностью на TypeScript, а одна и та же команда владеет и сервером, и клиентом.
- REST для вебхуков, публичных API и интеграций с партнерами, где требуется доступ, не зависящий от языка программирования.
Использование правильного инструмента для каждой задачи позволяет сохранить скорость внутренней разработки, обеспечивая при этом открытость, необходимую для внешних потребителей.
Итог: Замена REST на tRPC может избавить от дублирования артефактов контракта и выявлять ошибки прямо во время редактирования кода, но выгода проявляется только тогда, когда весь стек использует TypeScript, а команда готова к затратам на миграцию. Смешанная стратегия позволяет извлечь пользу, не ограничивая потребителей, не использующих TypeScript.
