tRPC gets praised as if it replaces every API style. It does not.
What it actually does very well is remove unnecessary coordination work inside a tightly coupled TypeScript stack. If your frontend and backend already live close together, and both are written in TypeScript, tRPC can cut a lot of duplicated typing and interface drift.
That is a real advantage. It is just not universal.
The Problem It Solves
In a lot of full-stack TypeScript apps, the same contract gets described three times:
input validation
backend handler types
frontend consumer types
That duplication is where bugs and stale assumptions creep in.
tRPC collapses a lot of that by letting the client infer procedure types directly from the server router:
import { initTRPC } from "@trpc/server";import { z } from "zod";const t = initTRPC.create();export const appRouter = t.router({ getUser: t.procedure .input(z.object({ id: z.string() })) .query(async ({ input }) => { return db.user.findById(input.id); }),});export type AppRouter = typeof appRouter;
On the client side, you no longer hand-maintain a second version of the contract:
import { createTRPCProxyClient, httpBatchLink } from "@trpc/client";import type { AppRouter } from "./server";const trpc = createTRPCProxyClient<AppRouter>({ links: [httpBatchLink({ url: "/api/trpc" })],});const user = await trpc.getUser.query({ id: "123" });
That is the part people like: fewer handwritten seams.
Why It Feels So Good
tRPC is excellent when:
the app is a monorepo or close equivalent
TypeScript is the language on both sides
the frontend is not meant to be a broad public API consumer
In that world, you get a very fast feedback loop. Rename a field on the server, and the client usually breaks at compile time instead of a week later in QA.
The Trade-Offs
tRPC is weaker when:
multiple languages need to consume the API
the API is public or partner-facing
the backend and frontend evolve independently
protocol-level contracts matter more than type inference convenience
That is where REST or gRPC usually makes more sense. Not because they are more modern, but because they are more decoupled.
A Better Framing
tRPC is not "the death of REST."
It is a very good fit for a specific category of product team:
one organization
one stack
one shared type system
If that is your situation, it is a strong option.
If it is not, forcing tRPC into the architecture usually creates a different kind of coupling problem.