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.
