Episode ini mengupas sejarah tRPC dari akar RPC klasik hingga kebangkitannya di komunitas TypeScript, masalah yang diselesaikannya dibanding REST dan GraphQL, serta kapan tRPC menjadi pilihan tepat untuk aplikasi internal, monorepo, dan rapid prototyping.

Sebelum menulis kode, kita perlu memahami mengapa tRPC ada. Setiap teknologi lahir dari rasa frustrasi terhadap cara lama — dan tRPC adalah jawaban atas frustrasi dua dekade: API yang duplikatif, client yang tidak tahu bentuk data yang dikirim server, dan tooling yang membutuhkan codegen.
Episode 1 membawa kalian menjelajahi sejarah tRPC, masalah yang diselesaikannya, perbandingannya dengan REST dan GraphQL, serta skenario yang paling tepat memakainya. Dengan memahami konteksnya, kalian akan tahu kapan harus memakai tRPC dan kapan tidak.
RPC sebenarnya bukan konsep baru. Sejak era CORBA dan XML-RPC, programmer sudah memanggil fungsi jarak jauh dengan nama. Masalahnya, mekanisme lama itu berat, kaku, dan tidak aman tipe. Di dunia modern, REST dan GraphQL menjawab masalah berbeda, tetapi keduanya tetap memisahkan server dan client secara tipe.
tRPC dimulai sekitar tahun 2021 oleh Alex Johansson, yang dikenal sebagai KATT di komunitas TypeScript. Ide awalnya sederhana: jika server dan client berada dalam satu project TypeScript, mengapa tidak memanfaatkan kompiler untuk menurunkan tipe dari server langsung ke client? Tidak ada schema terpisah, tidak ada generator, tidak ada duplikasi.
Versi awal tRPC adalah library RPC sederhana berbasis observables. Perkembangannya signifikan:
links, initTRPC, dan createTRPCReact, plus dukungan penuh React Query.router.merge, createCallerFactory, dan memperkuat dukungan Next.js App Router serta serverless.Evolusi ini mengarah ke satu tujuan: full-stack TypeScript dengan zero-boilerplate, di mana penambahan satu procedure langsung otomatis tersedia di client dengan tipe lengkap.
Dalam REST, bentuk data ditentukan URL dan method, tetapi tipe response hanya diketahui dari dokumentasi atau pengecekan manual. Contoh pola REST yang rentan error:
curl https://api.example.com/users/1
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"nama": "Arman"}'Tidak ada yang menjamin bahwa response GET /users/1 akan mengembalikan field nama. Developer harus menjaga kesesuaian secara manual, dan begitu satu field berubah, client bisa diam-diam pecah. tRPC menghilangkan masalah ini karena tipe procedure diturunkan langsung dari server.
GraphQL menyelesaikan masalah overfetch dan underfetch, tetapi butuh schema SDL terpisah, resolver yang dijaga konsistensinya dengan schema, dan client codegen seperti GraphQL Code Generator. Setiap perubahan schema memicu regenerasi tipe client.
tRPC memakai validator seperti zod sebagai satu-satunya sumber kebenaran, tanpa schema bahasa lain, tanpa resolver boilerplate, dan tanpa langkah codegen. Trade-off-nya: GraphQL unggul untuk public API yang dipakai banyak client berbeda, sedangkan tRPC unggul untuk server dan client yang dikelola tim yang sama.
Dengan tRPC, seluruh tipe hidup di satu codebase TypeScript. Client menerima tipe yang persis sama dengan server, dan editor menampilkan autocompletion untuk nama procedure, bentuk input, dan bentuk response:
import { createTRPCProxyClient, httpBatchLink } from "@trpc/client";
import type { AppRouter } from "./server/router";
const trpc = createTRPCProxyClient<AppRouter>({
links: [httpBatchLink({ url: "http://localhost:3000/trpc" })],
});
const user = await trpc.user.byId.query({ id: 1 });Salah menulis nama procedure seperti trpc.user.byID.query({ id: 1 }) akan ditolak compiler. Salah mengirim field pun akan ditolak sebelum aplikasi berjalan. Ini adalah type-safety end-to-end yang tidak dimiliki REST atau GraphQL tanpa tooling tambahan.
Karena tidak ada langkah generate, menambah fitur menjadi sangat cepat: definisikan procedure di server, dan client langsung memilikinya. Tidak ada sinkronisasi schema, tidak ada dokumentasi yang basi, dan tidak ada langkah build tambahan.
Satu perubahan di server bisa langsung diuji dari editor. Compiler memberi umpan balik seketika: jika kalian menghapus procedure yang masih dipakai client, error muncul di tempat pemakaiannya. Umpan balik seperti ini tidak mungkin didapat dari API yang dipisah file-nya.
Agar penilaian kalian seimbang, kenali batasan tRPC:
Batasan ini bukan berarti tRPC jelek — hanya berarti ia punya tempat yang jelas, sebagaimana REST dan GraphQL punya tempatnya masing-masing.
tRPC bukan pengganti semua API. Skenario yang paling tepat:
Sebaliknya, untuk public API yang dikonsumsi pihak ketiga, REST dengan OpenAPI atau GraphQL tetap lebih cocok karena ekosistem tooling dan dokumentasinya matang. Episode 16 nanti akan membahas integrasi tRPC dengan Next.js dan serverless untuk menutup jarak ini.
Info
tRPC dan REST bukan musuh. Banyak production app menggabungkan keduanya: tRPC untuk komunikasi internal antar layanan dalam monorepo, dan OpenAPI untuk endpoint publik.
Episode 1 membuka konteks besar di balik tRPC: lahir dari frustrasi duplikasi tipe, berkembang dari RPC sederhana menjadi full-stack framework, dan menawarkan type-safety end-to-end yang tidak dimiliki REST atau GraphQL tanpa tooling tambahan.
Inti yang harus dibawa pulang:
Di episode 2 selanjutnya kita akan membedah konsep dasar dan arsitektur utama tRPC — bagaimana tipe diinferensikan di balik layar, peran router, procedure, input, output, dan caller, serta adapter transport HTTP, WebSocket, dan serverless.