Web Development

REST vs GraphQL vs tRPC: Choosing an API Style in 2026

Three mature ways to build an API, three very different sets of trade-offs. How to choose based on your consumers, your team and your type system — not hype.

Marcus Webb

Senior Writer

Elena Ruiz

Fact Checked

Three different glowing pipelines delivering data packages to a central API service counter

Sooner or later every project needs an API, and in 2026 you have three mainstream, mature, well-documented ways to build one: classic REST, the query language GraphQL, and the TypeScript-native RPC layer tRPC. All three are production-proven. All three have excellent tooling. And picking the wrong one for your situation will tax your team for years.

The good news: the decision is much less about technology than about who calls your API. Let’s build that decision framework, then look at each option honestly.

The sixty-second version

RESTGraphQLtRPC
Best forPublic APIs, unknown clientsMany diverse frontends, big orgsInternal full-stack TS apps
ContractOpenAPI (optional)Schema (mandatory)TypeScript types (automatic)
Over/under-fetchingCommonSolved by designIrrelevant (you own both sides)
HTTP cachingExcellent (native)Hard (POST queries)Limited
Learning curveLowSignificantLow (if you know TS)
Client freedomAny languageAny languageTypeScript only
Versioning story/v1, /v2 or headersSchema evolution, deprecationDeploy client+server together
Three mature API styles, three different bets about who your consumers are.

If you only remember one heuristic, make it this:

Strangers → REST. Many frontends → GraphQL. Your own TypeScript monorepo → tRPC.

REST: the boring default that keeps winning

REST isn’t a technology — it’s a set of conventions over HTTP: resources as URLs, verbs as operations, status codes as outcomes. That simplicity is precisely why, decades in, it still powers the overwhelming majority of public APIs.

Where REST is unbeatable:

  • Unknown consumers. Anyone with an HTTP client in any language can call you. No SDK, no schema download, no runtime.
  • Caching. GET requests cache natively — in browsers, CDNs, proxies — with zero configuration. For read-heavy public data this is an enormous, often decisive advantage.
  • Tooling ubiquity. curl, Postman, API gateways, rate limiters, monitoring — everything speaks REST out of the box.

Where REST hurts:

  • Over- and under-fetching. The mobile team wants three fields; your endpoint returns forty. The dashboard needs data from five resources; that’s five round trips. You end up bolting on ?fields= parameters and /summary endpoints — a homemade, worse GraphQL.
  • No enforced contract. OpenAPI specs are great but optional, and they drift from reality unless you generate code from them (or them from code).

If you’re building a REST API in Node, we walk through the full setup — routing, validation, error handling, auth — in our Express REST API tutorial.

GraphQL: a query language, and an organizational tool

GraphQL inverts control: the server publishes a typed schema of everything available, and each client composes queries for exactly the data it needs — no more, no less, in one round trip.

query ArticlePage($slug: String!) {
  article(slug: $slug) {
    title
    publishedAt
    author { name avatarUrl }
    related(limit: 3) { title slug }
  }
}

That’s a page’s entire data requirement in one request, shaped by the consumer. Change what the page shows, change the query — no backend deploy.

Where GraphQL genuinely earns its keep:

  • Multiple heterogeneous clients. Web, iOS, Android, smart TV, partners — each with different data needs from the same graph. This is the environment GraphQL was invented for at Facebook, and it remains the honest use case.
  • Organizational decoupling. Frontend teams self-serve instead of filing “please add a field” tickets. In large companies this changes team dynamics more than any technical property.
  • A mandatory, introspectable contract. The schema is the documentation, and tooling (codegen, IDE autocomplete, linting against breaking changes) hangs off it beautifully.

The costs, honestly stated:

  • Server complexity. Resolvers, N+1 query problems (hello, DataLoader), query depth limiting, cost analysis to stop hostile queries — a production GraphQL server is a genuine piece of infrastructure.
  • Caching regression. Queries are usually POSTs to one endpoint, so HTTP caching is gone; you rebuild caching at the application layer (persisted queries help).
  • Complexity floor. For a single web frontend talking to its own backend, you’re paying the schema/resolver/codegen tax to solve coordination problems you don’t have.

tRPC: delete the API layer (for yourselves)

tRPC asks a sharp question: if your client and server are both TypeScript and deploy together, why maintain a serialization contract at all? Define procedures on the server; call them from the client as typed functions:

// server
export const appRouter = router({
  articleBySlug: publicProcedure
    .input(z.object({ slug: z.string() }))
    .query(({ input }) => db.article.findUnique({ where: { slug: input.slug } })),
});
// client — fully typed, autocompleted, no codegen step
const article = await trpc.articleBySlug.query({ slug: 'rest-vs-graphql-vs-trpc' });

Rename a field on the server and the client fails to compile. That end-to-end type safety — with no schema files and no code generation — is the entire pitch, and for full-stack TypeScript teams it’s a massive quality-of-life and correctness win.

The trade-offs are the flip side of the coupling:

  • TypeScript-only. The moment a Swift app, a partner, or a Python service needs your API, tRPC has nothing for them.
  • Client and server must move together. Fine in a monorepo with atomic deploys; painful across independently-released apps (mobile app stores, anyone?).
  • It’s RPC. You get functions, not a resource model — which is honest for internal use, but public APIs benefit from REST’s uniform interface.

Worth noting: React Server Components and server actions (covered in our server vs client components guide) now handle some of the same internal data-fetching territory, which is exactly why tRPC’s sweet spot is mutations-heavy, client-rich apps and non-Next stacks.

The decision, step by step

  1. Will unknown third parties call this API? → REST (with OpenAPI). End of analysis for the public surface.
  2. Do three-plus different client teams consume overlapping data? → GraphQL is likely worth its infrastructure.
  3. Is it your own TypeScript app, front and back in one repo? → tRPC (or server actions if you’re all-in on RSC).
  4. Read-heavy public content where CDN caching matters? → REST, no contest.
  5. Still unsure? → REST. It’s the choice you’ll regret least, and every developer you ever hire already knows it.

And remember these compose. A very common, very sane 2026 architecture: tRPC internally for the product app, a REST facade for public/partner access, and GraphQL only if/when client diversity actually materializes. Choosing an API style is not a wedding.

The decision, as a flow: strangers → REST; many client teams → GraphQL; your own TypeScript monorepo → tRPC.

Performance footnote

None of the three is “fastest” in general. REST wins read-heavy public workloads via HTTP caching; GraphQL wins chatty mobile screens by collapsing round trips; tRPC’s batching gives snappy internal apps with minimal effort. The real performance decision is usually where the data is served from — edge caching and static generation dwarf protocol differences, as our hosting platforms comparison shows in concrete numbers.

Final Thoughts

API style is a people decision wearing a technology costume. REST optimizes for strangers, GraphQL for many known teams, tRPC for one team moving fast in one language. Map your actual consumers — today’s and the realistic next two years’ — onto that sentence and the choice usually makes itself.

The one genuine mistake is choosing by fashion: adopting GraphQL for a solo project’s single frontend, or wedging tRPC into a public API. Boring correctness beats interesting architecture — your API is the part of your system you’ll live with longest.