Programista poświęcił dwa tygodnie na zastąpienie REST API przez tRPC w narzędziu wewnętrznym.

Dlaczego ta zmiana miała znaczenie

Stary stos technologiczny zmuszał nas do utrzymywania DTO, walidatora oraz oddzielnego zestawu typów TypeScript dla frontendu. Zmiana nazwy pola w backendzie sprawiała, że API wciąż zwracało status 200, interfejs użytkownika nadal się renderował, a błąd objawiał się jedynie jako wartości „undefined”. Klient zauważył problem przed kimkolwiek z zespołu. Kontrakty REST ukrywały problem, a dodatkowe pliki generowały koszty utrzymania, które nigdy się nie zwróciły.

Jak wyglądała konfiguracja REST

  • Specyfikacja OpenAPI – statyczny plik opisujący punkty końcowe (endpoints), który nigdy nie służył jako jedyne źródło prawdy (source of truth).
  • Krok generowania SDK klienta – zadanie CI, które tworzyło wrapper w JavaScript.
  • Kolekcja Postman – współdzielony artefakt testowy, z którego nikt nie korzystał.
  • Ręczne interfejsy TypeScript – pisane ręcznie typy, które musiały być synchronizowane z serwerem.

Każda zmiana w API dotykała co najmniej trzech z tych artefaktów, plus walidatora i wszelkich wywołań fetch w dalszej części aplikacji. Proces był powolny i podatny na błędy.

Jak tRPC odchudziło bazę kodu

tRPC eliminuje potrzebę posiadania oddzielnego pliku z kontraktem. Serwer eksportuje typ routera, a klient importuje ten sam typ. Zmiana nazwy pola w backendzie sprawia, że edytor natychmiast flaguje niezgodność – bez uruchamiania kodu czy konieczności wysyłania błędnych żądań. Programista usunął:

  • Plik specyfikacji OpenAPI.
  • Krok generowania SDK klienta.
  • Nieużywaną kolekcję Postman.
  • Folder z ręcznymi interfejsami TypeScript.

Repozytorium stało się lżejsze, a informacja zwrotna pojawiała się już podczas developmentu, a nie po wdrożeniu.

Ograniczenia tRPC

tRPC działa tylko wtedy, gdy obie strony komunikują się za pomocą TypeScript. Nie sprawdzi się, jeśli:

  • Zespół mobilny używa Swift lub Kotlin.
  • API musi być konsumowane przez zewnętrznych partnerów.
  • Potrzebujesz publicznego interfejsu niezależnego od języka (language-agnostic).

Czego faktycznie wymagała migracja

Dwutygodniowy wysiłek to było coś więcej niż tylko kopiowanie i wklejanie. Programista musiał:

  • Przepisać każde wywołanie fetch, aby korzystało z funkcji klienta tRPC.
  • Dostosować logikę obsługi błędów.
  • Zaktualizować komponenty UI, które polegały na stanach ładowania i ponawiania prób (retry), powiązanych z surowymi odpowiedziami HTTP.

Pytania, które warto zadać przed zmianą

  • Czy frontend i backend używają TypeScript? Bez wspólnego systemu typów tRPC traci swoją główną zaletę.
  • Czy ten sam zespół odpowiada za obie strony? Luki w odpowiedzialności mogą ponownie doprowadzić do rozbieżności w kontraktach (contract drift).
  • Czy naprawiasz konkretny błąd, czy goniący za trendami? Wzrost produktywności jest realny, ale zmiana powinna rozwiązywać istniejący problem.

Podejście hybrydowe na rok 2025

Wiele zespołów znajduje złoty środek, korzystając z obu stosów technologicznych:

  • tRPC dla wewnętrznych warstw aplikacji, gdzie baza kodu jest w całości w TypeScript, a ten sam zespół zarządza serwerem i klientem.
  • REST dla webhooków, publicznych API i integracji z partnerami, gdzie wymagany jest dostęp niezależny od języka programowania.

Używanie odpowiedniego narzędzia dla każdego obszaru pozwala zachować szybkość rozwoju wewnętrznego, jednocześnie zapewniając otwartość niezbędną dla zewnętrznych konsumentów.

Podsumowanie: Zastąpienie REST przez tRPC może wyeliminować duplikujące się artefakty kontraktów i ujawniać błędy już na etapie edycji kodu, ale korzyści materializują się tylko wtedy, gdy cały stos technologiczny korzysta z TypeScript, a zespół jest w stanie udźwignąć koszt migracji. Strategia mieszana pozwala czerpać korzyści bez blokowania konsumentów nieużywających TypeScript.