Разработчик потратил две недели на замену 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.