Loading...
Loading...
After two years of REST APIs, I moved to tRPC for my side projects. Here is what actually changed.
I spent about two years writing REST APIs before I gave tRPC a serious shot. My reason for switching was boring: I was tired of writing types twice.
In a typical setup with a Next.js frontend and an Express backend, you write a Zod schema on the server, then write a matching TypeScript type (or interface) on the client. If you forget to sync them, you find out at runtime. It is not a catastrophe, but it adds up.
tRPC removes that by sharing your router types directly with the frontend. No code generation, no GraphQL schema files, no REST contract docs to maintain. You just import the type from your server and your editor already knows what the response looks like.
Day-to-day, the biggest difference is autocomplete. When I call trpc.user.getById.query({ id }) on the client, TypeScript knows exactly what comes back. I do not have to open another tab to check the API docs I wrote three weeks ago.
Refactoring is also faster. If I rename a field on the server, the client breaks immediately at the type level, not at runtime. That alone saves me from a category of bugs I used to encounter regularly.
HTTP verbs and status codes. This sounds minor until you are debugging a caching issue and you cannot just curl an endpoint and read the response headers. tRPC uses POST for everything by default (you can opt into query for GET, but it is not automatic), which means your standard HTTP debugging tools feel slightly awkward.
Documentation is the other thing. REST APIs are easy to document with OpenAPI. tRPC has some tools for this, but nothing as mature. If you are building something other people will integrate with, REST is still the cleaner choice.
Public APIs. If third-party clients need to consume your API, tRPC is not the right tool. The type-sharing only works within a TypeScript monorepo.
Microservices with polyglot teams. If your backend team writes Go and your frontend team writes TypeScript, the main benefit disappears.
For a solo project or a small team working in a TypeScript monorepo, though, it is genuinely good. Not because it is clever, but because it removes a whole class of problems I used to deal with manually.