TL;DR
Choose tRPC v11 for monorepo-first full-stack TypeScript apps, oRPC when you want tRPC-like DX plus OpenAPI output, and ts-rest when standard REST contracts still matter to your architecture.
Quick Comparison
| Library | npm package | Weekly downloads | Latest | Best for | Biggest tradeoff |
|---|---|---|---|---|---|
| oRPC | @orpc/server | ~353K/week | 1.14.0 | Teams that want procedure-style TypeScript APIs without giving up OpenAPI generation and schema flexibility. | Smaller ecosystem and fewer battle-tested examples than tRPC. |
| tRPC v11 | @trpc/server | ~3.1M/week | 11.16.0 | Full-stack TypeScript monorepos, especially React apps that want the shortest path from server procedures to typed client hooks. | The model is most attractive when both sides are TypeScript and closely coupled. |
| ts-rest | @ts-rest/core | ~458K/week | 3.52.1 | Teams that want strong TypeScript contracts while preserving plain REST semantics and HTTP conventions. | It feels less magical than RPC because REST constraints remain part of the design work. |
Why this matters in 2026
Type-safe APIs are no longer a niche TypeScript luxury. They are the default expectation for teams that own both client and server code.
What changed is that the market matured into three distinct answers. tRPC proved that many full-stack teams are happy with procedure-style APIs when it buys speed and type safety. ts-rest proved that some teams still need URLs, verbs, and standard HTTP contracts because other consumers and tooling depend on them. oRPC now matters because it tries to narrow that gap instead of forcing an all-or-nothing RPC versus REST choice.
In 2026, the right decision usually depends less on syntax preference and more on whether your API has to be shared with non-TypeScript consumers, public docs, or broader platform tooling.
What actually changes the decision
- If your frontend and backend live in one TypeScript codebase, tRPC v11 is still the easiest default.
- If OpenAPI generation and multi-schema support matter, oRPC becomes much more compelling.
- If your architecture still depends on standard REST semantics, ts-rest is usually the most honest choice.
- The deeper your API must serve non-TS consumers, third-party integrations, or platform-wide governance, the less attractive a pure RPC model becomes.
Package-by-package breakdown
oRPC
Package: @orpc/server | Weekly downloads: ~353K | Latest: 1.14.0
oRPC is interesting because it keeps the procedure-oriented developer experience many teams like from tRPC while taking OpenAPI and schema interoperability more seriously.
import { os } from '@orpc/server';
import { z } from 'zod';
export const getUser = os
.input(z.object({ id: z.string() }))
.route({ method: 'GET', path: '/users/{id}' })
.handler(async ({ input }) => ({ id: input.id }));
Best for: Teams that want procedure-style TypeScript APIs without giving up OpenAPI generation and schema flexibility. Tradeoff: Smaller ecosystem and fewer battle-tested examples than tRPC.
Strengths:
- OpenAPI output is a real differentiator
- Good fit for teams that want newer schema flexibility
- Useful middle ground between pure RPC DX and contract-driven APIs
Watch-outs:
- Newer ecosystem
- Fewer community recipes than tRPC
- You still need to choose how far toward REST or RPC you want to lean in practice
tRPC v11
Package: @trpc/server | Weekly downloads: ~3.1M | Latest: 11.16.0
tRPC remains the strongest default when the goal is simple: move fast inside one TypeScript application boundary.
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(({ input }) => ({ id: input.id })),
});
Best for: Full-stack TypeScript monorepos, especially React apps that want the shortest path from server procedures to typed client hooks. Tradeoff: The model is most attractive when both sides are TypeScript and closely coupled.
Strengths:
- Mature ecosystem and community knowledge
- Excellent React and TanStack Query integration
- Very high leverage in monorepos and app-router style full-stack apps
Watch-outs:
- Harder to justify for public APIs
- Less aligned with teams that need OpenAPI-first governance
- Can become awkward when non-TypeScript consumers enter the picture
ts-rest
Package: @ts-rest/core | Weekly downloads: ~458K | Latest: 3.52.1
ts-rest is the right option when you want end-to-end types but refuse to pretend HTTP conventions no longer matter.
import { initContract } from '@ts-rest/core';
import { z } from 'zod';
const c = initContract();
export const contract = c.router({
getUser: {
method: 'GET',
path: '/users/:id',
pathParams: z.object({ id: z.string() }),
responses: { 200: z.object({ id: z.string() }) },
},
});
Best for: Teams that want strong TypeScript contracts while preserving plain REST semantics and HTTP conventions. Tradeoff: It feels less magical than RPC because REST constraints remain part of the design work.
Strengths:
- Honest REST model
- Easier fit with public APIs and broader platform tooling
- Strong option when contract sharing matters more than procedure ergonomics
Watch-outs:
- More explicit API design work
- Less frictionless than tRPC for internal-only apps
- Some teams expecting RPC-style speed may find it more verbose than they want
Which one should you choose?
- Choose oRPC when you want modern RPC ergonomics but cannot ignore OpenAPI and schema interoperability.
- Choose tRPC v11 when you control both sides of a TypeScript app and want the highest-velocity developer experience.
- Choose ts-rest when the API must remain recognizably RESTful for humans, tooling, and non-TypeScript consumers.
Final recommendation
For internal TypeScript-heavy applications, tRPC v11 is still the best default. oRPC is the most interesting challenger because it solves real problems tRPC deliberately ignores. ts-rest is the better choice whenever your architecture still benefits from plain HTTP contracts more than from RPC convenience.
Related reading
tRPC v11 vs ts-rest 2026 · Hono vs Fastify vs NestJS 2026 · tRPC vs GraphQL