· trpc / rest / openapi

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 · 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

ItemDetail
Latest stablev11.17.0 (2026-04-28)
v11 GAMarch 21, 2025
TypeScript minimum5.7.2
Node.js minimum18
Next.js App RouterFirst-class (RSC prefetch, SSE, streaming)
TanStack Queryv5 required (isPending, not isLoading)
Real-timeSSE recommended; WebSocket available for bidirectional
OpenAPI generation@trpc/openapi 11.x.x-alpha
Hono adapterNo dedicated adapter in v11; use tRPC Fetch adapter
Key competitor to watchoRPC v1.0 (tRPC DX + native OpenAPI, Dec 2025)
Notable fix in v11.17.0React 19 proxy coercion in createInnerProxy

Verdict

ContextPick
Full-stack TypeScript monorepo, internal onlytRPC
Next.js + Vercel, one frontend, one backendtRPC
Public API with external consumersREST + OpenAPI
Mobile clients (iOS, Android)REST + OpenAPI
Multi-language services in the call chainREST + OpenAPI
Large org, distinct teams, separate reposREST + OpenAPI
Edge API, Cloudflare WorkersHono RPC or REST + OpenAPI
Monorepo needing OpenAPI for one external endpointtRPC + @trpc/openapi (evaluate alpha risk)
Greenfield, evaluating all options in 2026Benchmark 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