Skip to content
← All posts

Backend ServicesBy 26 Aug 20263 min read

REST vs GraphQL vs tRPC: Choosing the Right API Style

Each API style solves different problems. A practical comparison of REST, GraphQL and tRPC — strengths, costs, and which fits public APIs, mobile apps and full-stack TypeScript teams.

REST vs GraphQL vs tRPC: Choosing the Right API Style

Every backend exposes an API, and the style you choose shapes how fast clients can be built, how easy the API is to secure and cache, and how painful changes become later. The three most common choices today are REST, GraphQL and tRPC.

Three API stylesPick based on who consumes the API and how varied their data needs are.

REST

Resources identified by URLs, manipulated with HTTP methods:

GET    /students?classId=12
POST   /students
PATCH  /students/42
DELETE /students/42

Strengths

  • Universally understood; any language or tool can call it.
  • Uses HTTP fully: status codes, caching headers, CDNs.
  • Straightforward to secure, rate-limit and document with OpenAPI.

Costs

  • Clients may over-fetch (receiving fields they don't need) or under-fetch (needing several calls for one screen).
  • Versioning requires discipline.

Best for: public APIs, integrations, and most CRUD-style backends.

GraphQL

Clients send a query describing exactly the data they need, against a typed schema:

query StudentCard($id: ID!) {
  student(id: $id) {
    name
    class { name }
    attendance(last: 5) { date status }
  }
}

Strengths

  • One request fetches exactly what a screen needs — valuable for mobile clients on slow networks.
  • A strongly typed schema serves as documentation and enables code generation.
  • Evolves without versions by adding fields and deprecating old ones.

Costs

  • HTTP caching is harder; queries usually go through one POST endpoint.
  • Needs protection against expensive queries (depth and complexity limits).
  • N+1 queries in resolvers unless you use batching (DataLoader).
  • Authorisation must be enforced per field and object, not per route.

Best for: products with many different clients and data-rich screens.

tRPC

Type-safe remote procedure calls for TypeScript monorepos. The client imports the server's router type, so calling an endpoint feels like calling a local function — with autocomplete and compile-time errors when the backend changes.

const student = await trpc.student.byId.query({ id: "42" }); // fully typed, no codegen

Strengths

  • End-to-end type safety without schemas or code generation.
  • Very fast development for full-stack TypeScript teams.

Costs

  • Tied to TypeScript on both sides; not suitable as a public API.
  • Less standard tooling for caching and documentation.

Best for: internal APIs where the same team owns the Next.js (or React) frontend and the Node.js backend.

A Pragmatic Combination

Many teams mix styles: tRPC or Server Actions for their own web app, REST with OpenAPI for mobile apps and partners, and webhooks to push events to integrators. The styles are interfaces over the same domain logic — keep business rules in a shared service layer, not in the API layer.

Key Takeaways

  • REST is the safest default and the best choice for public APIs.
  • GraphQL suits many clients with varied data needs, but needs query limits and batching.
  • tRPC gives unmatched developer speed for full-stack TypeScript teams.
  • Mixing styles is normal; keep business logic independent of the API layer.

Sources

More posts