tRPC vs REST: When to Drop OpenAPI in TypeScript Apps
Use tRPC for full-stack TypeScript monorepos where type drift bites. Use REST + OpenAPI for public APIs and non-TypeScript consumers. In 2026 you need both.
By Ethan · Updated May 26, 2026
2,197 words · 11 min read
Use tRPC if you own both ends of a TypeScript monorepo and type drift keeps causing bugs. Use REST + OpenAPI if your API has any non-TypeScript consumers — mobile apps, third-party integrations, public endpoints. In 2026, the practical answer for most teams isn’t a choice between them: run tRPC as the internal BFF layer, REST + OpenAPI at any organizational or public-facing boundary.
Who this is for
TypeScript and Node.js developers evaluating whether tRPC is worth adopting. You already know REST + OpenAPI — what a schema is, what a code generator does, why you’d have both. If that’s new territory, this isn’t the right article yet.
The type drift problem
You rename a field on the backend. The TypeScript frontend compiles clean. The bug ships. Two days later you’re bisecting why user addresses stopped saving.
This class of bug — the frontend calling a field the backend silently renamed — is what OpenAPI + codegen tries to prevent. The codegen generates a typed client from the schema. When you run it. When the schema is current. When CI enforces that run. When nobody hand-edited the generated output.
That’s a lot of “whens.” In fast-moving monorepos, schema drift is the failure mode that a CI check catches on a good week and a production incident catches on a bad one. The linter doesn’t save you; the tests don’t save you if they mock the API. The bug ships because two things claimed to be in sync and weren’t.
tRPC’s answer: make schema drift impossible by construction. The frontend imports types directly from the backend package. Rename a field server-side and every call site errors at compile time, instantly, without any codegen step. There is no separate schema to keep in sync because there is no schema — TypeScript is the contract.
That’s the core value proposition. Whether it’s worth the constraints depends on your specific context.
What tRPC actually is
Not “type-safe RPC” in the sense of gRPC or Thrift. No interface definition language. No binary protocol. No wire format beyond JSON. tRPC runs over plain HTTP and derives its type safety entirely from TypeScript’s structural inference.
You define procedures on the server:
// packages/api/src/router.ts
import { publicProcedure, router } from './trpc';
import { z } from 'zod';
export const appRouter = router({
user: router({
byId: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return db.user.findUniqueOrThrow({ where: { id: input.id } });
}),
create: publicProcedure
.input(z.object({ name: z.string(), email: z.string().email() }))
.mutation(async ({ input }) => {
return db.user.create({ data: input });
}),
}),
});
export type AppRouter = typeof appRouter;
The client imports that type — not the implementation, only the AppRouter type — and gets full inference:
// apps/web/src/components/UserProfile.tsx
const { data } = trpc.user.byId.useQuery({ id: userId });
// data is typed from DB return shape — no manual annotation needed
const createUser = trpc.user.create.useMutation();
// input is typed; wrong field name or wrong type = compile error
TypeScript erases the type import at build time. Your database code never ships to the browser. The contract between frontend and backend is TypeScript’s type system, not a YAML file.
That’s end-to-end inference with zero codegen. The “zero” matters: it can’t be stale, it can’t be forgotten, it can’t diverge.
tRPC v11.17.0 (released 2026-04-28) requires TypeScript ≥ 5.7.2 and Node.js ≥ 18. The v11 GA shipped March 21, 2025.
If GraphQL is also on your shortlist, see tRPC vs GraphQL — the evaluation criteria differ significantly from REST.
Where tRPC wins
Full-stack TypeScript monorepo
The canonical setup is the T3 Turbo pattern: a packages/api workspace that houses the tRPC router, consumed by apps/web as a dev dependency. Cal.com runs this way at scale. Ping.gg — the project of tRPC’s creator — runs this way. Dozens of YC batch companies from 2023–2025 started on T3 Stack.
The benefit compounds over time. Your backend team renames a procedure to better reflect what it actually does. Every TypeScript error in apps/web tells you exactly which call sites need updating. That’s a 10-minute refactor, not a 2-day integration test fire.
The T3 Turbo stack typically pairs tRPC with Prisma or Drizzle for the database layer. If you haven’t settled on an ORM yet, best TypeScript ORM in 2026 covers the current options.
The monorepo constraint is real: tRPC requires TypeScript sharing. If you’re not in a monorepo, you publish a private npm package containing only the router types and bump it on every API change. That works — it’s documented — but it adds coordination overhead that erodes the DX benefit past a certain team size. Keep this constraint in mind before committing.
Rapid iteration with small teams
When your API consumer count is “us,” tRPC dramatically reduces the refactoring tax. Move a procedure between routers. Add an input field. Change a return type. TypeScript catches every affected site immediately. No schema to update, no codegen step to remember.
Performance is not a concern
Benchmarks on AWS c5.xlarge (4 vCPU, 8 GB RAM, Node.js 20.x, 1,000 concurrent users via Artillery) show tRPC within 7–9% of REST HTTP/2 on throughput. Simple CRUD: REST HTTP/2 at 578ms average vs. tRPC at 623ms. Complex queries: REST HTTP/2 at 812ms vs. tRPC at 891ms.
For browser calls, the difference is negligible — network latency dominates, not serialization. Your bottleneck isn’t tRPC.
Next.js App Router and Vercel
tRPC v11 ships first-class Next.js App Router support. Prefetch procedures inside React Server Components; the pending promise is picked up client-side and hydrates the TanStack Query cache automatically.
For Next.js apps on Vercel, this means tRPC procedures slot into the same edge caching and streaming infrastructure as any RSC. No extra infrastructure, no proxy config. SSE subscriptions via httpSubscriptionLink work on Vercel Edge out of the box — tRPC v11 recommends SSE over WebSockets for most real-time use cases because SSE is simpler to set up, CDN-compatible, and browsers reconnect automatically on drop.
Where REST + OpenAPI wins
Public APIs and third-party consumers
If you publish an API that someone else calls — mobile apps, partners, external developers — tRPC is not a practical choice. The TypeScript requirement is a hard constraint. Swift, Kotlin, Python, Go, Ruby: none of them can consume a tRPC router natively.
@trpc/openapi is the bridge: it generates an OpenAPI 3.1 spec from your tRPC router. It exists. It works. It is alpha in v11.x. Subscriptions are excluded. APIs may change without notice. Treating alpha software as your production-critical public API contract is a risk that most teams shouldn’t take.
REST + OpenAPI has no equivalent constraint. One spec, clients in any language, standard tooling everywhere. Postman, Insomnia, AI agent MCP integrations, API gateways, enterprise contract negotiation: all consume OpenAPI natively. Your partner’s Go service doesn’t need to know anything about your internal TypeScript setup.
Multi-language teams and large org boundaries
tRPC requires TypeScript sharing. Separate repos, separate release cadences, or any non-TypeScript service in the call chain all break the model.
Large organizations with distinct teams, distinct tech stacks, or explicit team-API-team contracts are exactly where REST + OpenAPI earns its overhead. The schema is a published contract. You version it, gate breaking changes behind a version bump, and coordinate through the schema rather than through shared TypeScript. That’s bureaucracy, but it’s bureaucracy that scales.
The 2026 state of OpenAPI codegen is meaningfully better than it was in 2022. Speakeasy, Hey API, and Orval all generate typed, ergonomic TypeScript clients. OpenAPI 3.1 fully aligns with JSON Schema draft 2020-12. The tooling gap between tRPC’s zero-codegen DX and a well-maintained OpenAPI pipeline has narrowed considerably.
Cloudflare Workers and edge deployments
For public-facing APIs at the edge, Cloudflare Workers + Hono is the 2026 reference architecture for multi-language APIs. Hono v4 ships its own built-in typed RPC — distinct from tRPC — that gives TypeScript teams server-to-client type inference without the tRPC dependency. Combined with @hono/zod-openapi, you get an OpenAPI 3.1 spec, edge performance, and TypeScript types, without requiring every consumer to write TypeScript.
One detail worth knowing: tRPC v11 does not ship a dedicated Hono adapter; the recommended deployment path on Cloudflare Workers is tRPC’s Fetch adapter (docs). If you’re evaluating options for a new edge API, Hono’s own RPC is worth a direct benchmark against your workload before committing to either.
Migration path
REST → tRPC (incremental)
No big-bang rewrite needed. Run tRPC alongside your existing REST endpoints. Pick one internal endpoint — user preferences, dashboard data, something low-stakes — wrap it in a procedure, wire up the client, and validate that the DX improvement is real in your specific codebase before expanding.
Most teams that adopt tRPC start small, prove value on one route, then migrate internal endpoints over months rather than weeks. The coexistence story is clean: tRPC and Express (or Fastify) run in the same process, on the same port, under different path prefixes.
tRPC → REST (the escape hatch)
The exit from tRPC is documented and real:
@trpc/openapi: generates OpenAPI 3.1 from your router (alpha in v11.x; subscriptions excluded). Use it cautiously for internal documentation; don’t depend on it as a production public contract yet.- ts-rest: contract-first REST with OpenAPI 3.1 output. Keeps TypeScript safety, reintroduces the schema layer explicitly — useful if you want the tRPC DX but need an OpenAPI artifact.
- oRPC v1.0 (December 2025): tRPC-compatible DX with native OpenAPI generation, 1.6× faster type checking, and roughly half the bundle size vs. tRPC. For greenfield projects in 2026, it’s worth a serious evaluation before defaulting to tRPC.
Neither direction is a permanent trap. The cost to switch is effort, not impossibility.
The dual-interface architecture
The 2026 consensus for teams that outgrow tRPC-only: run tRPC as the frontend BFF layer for fast internal iteration, expose REST + OpenAPI at external or inter-team boundaries. Two routers, one monorepo, clean separation. tRPC procedures for the web app; a separate Fastify or Express router with OpenAPI decorators for the public API. Each consumer gets the interface that suits it.
This is described as a “dual interface” pattern in several 2025–2026 developer write-ups, and it’s the honest answer to “drop the OpenAPI?” — no, but you can scope where it lives.
2026 ecosystem snapshot
| Item | Detail |
|---|---|
| Latest stable | v11.17.0 (2026-04-28) |
| v11 GA | March 21, 2025 |
| TypeScript minimum | 5.7.2 |
| Node.js minimum | 18 |
| Next.js App Router | First-class (RSC prefetch, SSE, streaming) |
| TanStack Query | v5 required (isPending, not isLoading) |
| Real-time | SSE recommended; WebSocket available for bidirectional |
| OpenAPI generation | @trpc/openapi 11.x.x-alpha |
| Hono adapter | No dedicated adapter in v11; use tRPC Fetch adapter |
| Key competitor to watch | oRPC v1.0 (tRPC DX + native OpenAPI, Dec 2025) |
| Notable fix in v11.17.0 | React 19 proxy coercion in createInnerProxy |
Verdict
| Context | Pick |
|---|---|
| Full-stack TypeScript monorepo, internal only | tRPC |
| Next.js + Vercel, one frontend, one backend | tRPC |
| Public API with external consumers | REST + OpenAPI |
| Mobile clients (iOS, Android) | REST + OpenAPI |
| Multi-language services in the call chain | REST + OpenAPI |
| Large org, distinct teams, separate repos | REST + OpenAPI |
| Edge API, Cloudflare Workers | Hono RPC or REST + OpenAPI |
| Monorepo needing OpenAPI for one external endpoint | tRPC + @trpc/openapi (evaluate alpha risk) |
| Greenfield, evaluating all options in 2026 | Benchmark oRPC v1.0 first |
Pick tRPC if you control both frontend and backend in a TypeScript monorepo, your consumers are internal TypeScript code, and type drift is causing real pain.
Pick REST + OpenAPI if anyone outside your TypeScript codebase calls your API, the schema is a published contract, or you need standard tooling interop.
On “drop the OpenAPI?”: the @trpc/openapi alpha status answers this directly. In 2026, the bridge is being built — but you wouldn’t build a production public API contract on alpha software. Use tRPC where it’s a clear fit; keep REST + OpenAPI where the contract matters more than the ergonomics.
Caveats
Performance numbers cited here come from a third-party benchmark on AWS c5.xlarge, Node.js 20.x, Artillery. Your workload differs; run your own benchmarks before making architectural decisions based on throughput figures.
The affiliate links to Vercel and Cloudflare Workers in this article earn toolchew a commission. tRPC runs on any Node.js host. Hono runs on any edge runtime. These platforms appear because they’re the canonical deployment targets for each tool in 2026, not because the commission influenced the recommendation.
References
- tRPC v11 announcement
- tRPC v11.17.0 release notes
- tRPC subscriptions docs (SSE vs WebSocket)
- tRPC OpenAPI alpha docs
- tRPC discussion: monorepo not mandatory
- Performance benchmark: tRPC vs gRPC vs REST (metatech.dev, 2025)
- oRPC v1.0 release (InfoQ, Dec 2025)
- Hono RPC docs
- Exporting tRPC types for multi-repo setups
- tRPC vs REST: practical migration guide (Dev.to)
- tRPC vs OpenAPI comparison (Medium)