tRPC vs GraphQL vs REST for TypeScript 2026
TL;DR
For TypeScript monorepos and full-stack Next.js applications, tRPC eliminates the API boundary entirely — procedures are just TypeScript functions with end-to-end type safety and zero schema files. GraphQL is the right choice when your API must serve multiple clients with different data requirements (mobile, web, third parties) or when your team is large enough to benefit from a self-documenting schema. REST remains the dominant API style in 2026 (70%+ of job listings reference REST), the easiest to reason about, and the most compatible with existing tooling. Most production systems combine two or more patterns — REST for public/partner APIs, tRPC or GraphQL for internal full-stack data fetching.
Key Takeaways
- tRPC: Best DX for TypeScript-only full-stack apps; not a public API protocol
- GraphQL: Best fit for multi-client apps and large teams; overhead for small teams
- REST: Universal compatibility, simplest mental model, still dominant in production
- All three can coexist — many apps use tRPC internally + REST externally
Quick Comparison
| tRPC | GraphQL | REST | |
|---|---|---|---|
| Protocol | RPC over HTTP (proprietary) | Query language over HTTP | HTTP verbs + resources |
| Schema format | TypeScript (source of truth) | SDL (.graphql files) | OpenAPI / none |
| Type safety | End-to-end, automatic | Generated (codegen) | Generated or manual |
| Type inference | Automatic (inferRouterOutputs) | Via graphql-codegen | Via openapi-typescript |
| Client coupling | Tight (must share types) | Loose (schema contract) | Loose (HTTP contract) |
| Multi-client support | Poor (single TS codebase) | Excellent | Excellent |
| Learning curve | Low for TS devs | Medium-high | Low |
| Caching | React Query / built-in | Apollo / normalized | HTTP cache headers |
| Subscriptions | Built-in (websockets) | Built-in | SSE or polling |
| Job market | ~15% TS jobs (2026) | ~25% enterprise | ~70% overall |
| Best for | TS monorepos, Next.js | Multi-client, teams | Universal, public APIs |
Type Safety Model
Each approach has a fundamentally different philosophy on type safety.
tRPC shares types directly. The server defines procedures using TypeScript functions; the client imports the router type and calls procedures with full autocomplete and compile-time checking. There is no schema file, no code generation step, and no sync issue between server and client — they share the same TypeScript codebase.
// Server
const router = t.router({
getUser: t.procedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return db.user.findUnique({ where: { id: input.id } })
}),
})
export type AppRouter = typeof router
// Client (same repo or monorepo package)
import type { AppRouter } from "../server/router"
const trpc = createTRPCProxyClient<AppRouter>({ ... })
const user = await trpc.getUser.query({ id: "123" })
// user is fully typed: { id: string; name: string; email: string; ... }
GraphQL uses a schema as the contract. Type safety requires running graphql-codegen to generate TypeScript types from the schema. When types are generated, the DX is excellent — React Query hooks are typed, variables are validated, response types are correct. The overhead is the codegen step and the discipline to keep it running in CI.
REST can achieve type safety through OpenAPI + openapi-typescript code generation. Many teams skip this and write manual types, leading to drift between API documentation and client usage. When done properly with generated types, REST is reasonably type-safe. When done casually, it's the least type-safe of the three options.
Setup Complexity
tRPC has the lowest initial setup for TypeScript monorepos. With the T3 stack (create-t3-app) or a manual Next.js setup, you can have a working tRPC router in under 30 minutes. The setup requires @trpc/server, @trpc/client, and a server adapter (Next.js, Express, Fastify). Zod is the standard input validator.
GraphQL has higher setup overhead. You need a GraphQL server (Apollo Server, Yoga, or Pothos), a schema definition, resolvers, and a client library (Apollo Client, urql, or React Query with the graphql-request adapter). Running graphql-codegen in watch mode adds to the development setup. For small teams or simple applications, this overhead is hard to justify.
REST has near-zero setup beyond your HTTP framework. Express, Fastify, Hono, or Next.js route handlers all support REST with no additional libraries. The investment in OpenAPI tooling is optional and additive.
When tRPC Makes Sense — and When It Doesn't
tRPC is genuinely transformative for its target use case: a single TypeScript codebase serving a single client. The T3 stack pattern (Next.js + tRPC + Prisma + NextAuth) eliminates an entire category of type sync bugs and reduces API boilerplate substantially.
tRPC's hard limits are important to understand:
- Client and server must share a TypeScript codebase. tRPC doesn't work for public APIs, third-party integrations, or non-TypeScript clients (mobile apps in Swift/Kotlin, partners consuming your API).
- tRPC is RPC, not REST. There are no resource URLs, no HTTP caching at the URL level, no standard clients. API consumers that expect REST semantics are not compatible.
- Scaling team boundaries is awkward. When the team grows large enough to have separate backend and frontend teams with separate repos, tRPC's shared-type model requires careful monorepo management or API versioning strategies.
For applications that will have a public API, a mobile client, or third-party integrations, tRPC is not the right choice for the external-facing layer (though it can still be used internally).
GraphQL's Current Position
GraphQL adoption peaked around 2021-2022 and has settled at roughly 25% of enterprise applications in 2026 — a significant drop from projections at the peak of hype. The pattern that emerged: GraphQL excels for large organizations with many clients and complex data graphs (Netflix, GitHub, Shopify), but adds more complexity than value for most standard CRUD applications.
The rise of React Server Components (RSC) in Next.js has also reduced one of GraphQL's primary advantages — avoiding over-fetching on the client. RSCs let you fetch exactly the data you need server-side without a client query language, eliminating the N+1 problem for many standard use cases.
GraphQL remains the best choice when:
- Multiple client types need different data shapes (mobile app needs less than web app)
- You're building an API consumed by external developers who need discoverability
- Your data model is a genuine graph (social networks, knowledge bases)
- Team size justifies schema-first API design with separate frontend/backend teams
See our REST vs GraphQL vs gRPC vs tRPC deep dive for a four-way comparison that includes gRPC for internal service communication.
REST in 2026
REST's staying power comes from its simplicity and universal tooling support. Every HTTP client in every language speaks REST. OpenAPI tooling (Swagger UI, Redoc, Stoplight) is mature. Caching is HTTP-native. Load balancers, CDNs, and API gateways all understand REST semantics.
For public APIs that external developers will consume, REST is still the right default. The developer experience of curl https://api.example.com/users/123 is simpler than explaining GraphQL queries or tRPC types to a developer evaluating your API.
REST's weakness is type safety across the client-server boundary — this is only as good as your OpenAPI documentation discipline. Tools like openapi-typescript and zod-openapi have improved this, but it requires more intentional setup than tRPC or GraphQL codegen.
Real-World Patterns
Most mature applications use a combination:
| Layer | Common Choice |
|---|---|
| Internal full-stack data fetching (Next.js + TypeScript) | tRPC |
| Partner/external developer API | REST + OpenAPI |
| Legacy backend with complex data relationships | GraphQL |
| Mobile client data fetching | REST or GraphQL |
| Internal microservice communication | gRPC or REST |
This combination is not a failure to commit — it's pragmatic architecture. Use tRPC where you control both sides and want maximum DX; expose REST for external consumers; use GraphQL when you need a public schema contract with flexible queries.
tRPC v11 and the 2026 Ecosystem
tRPC v11, released in late 2025, was the release that fully aligned tRPC with the Next.js App Router model and settled its position in the 2026 TypeScript stack.
The two headline additions in v11 are React Server Component support and streaming responses via iterables. RSC support means tRPC procedures can be called directly from server components without a client-side fetch — you get the full type-safety of tRPC with the performance characteristics of server-side rendering. Streaming via iterables enables procedures that yield values incrementally rather than returning a single response, which is useful for AI streaming outputs, long-running data exports, and real-time feeds.
The v11 integration with TanStack Query v5 is also improved — the adapter generates properly typed hooks with full v5 API support (the options object API, enabled flag, select transforms), resolving friction that users hit with the v10 adapter when TanStack Query v5 shipped.
The T3 Stack in 2026 reflects these changes. create-t3-app now scaffolds with tRPC v11, Drizzle ORM (replacing Prisma as the default), and Clerk (replacing NextAuth). The stack defaults represent community consensus around what produces the best DX in a Next.js 15 App Router monorepo. New T3 apps use tRPC for reactive data queries, Server Actions for mutations, and Clerk's middleware for auth — a pattern where tRPC's role is more focused than in v10 apps.
The broader tRPC ecosystem matured alongside v11. trpc-openapi generates valid REST/OpenAPI endpoints from tRPC routers — each procedure can be annotated with an HTTP method and path, producing a spec-compliant REST API alongside the native tRPC interface. This bridges the common internal/external API split: teams can use tRPC internally for full type-safety while exposing REST endpoints for partner integrations or mobile clients without maintaining a separate API layer. zodios is a notable REST alternative taking similar DX goals — a typed REST client using Zod schemas as the contract — for teams that want tRPC-like type safety over a conventional REST API.
When to Use Which
Choose tRPC if:
- TypeScript monorepo with a single client type (web app)
- Full-stack Next.js application where DX is the top priority
- Small to medium team where shared types eliminate sync errors
- You can accept that the API is not publicly consumable
Choose GraphQL if:
- Multiple client types need different data shapes
- External developers will discover and query your API
- Large team benefits from schema-first API contracts
- Your data is genuinely graph-shaped with complex relationships
Choose REST if:
- Building a public API for third-party integrations
- Non-TypeScript clients or teams consuming the API
- Simplicity and universal tooling compatibility matter
- Team is small and doesn't need the query flexibility of GraphQL
For the input validation layer in any of these API styles, see Zod vs Yup vs Joi 2026. For backend platform choices that influence your API layer, see our Convex vs Supabase comparison.