DEV Community

Otto
Otto

Posted on

GraphQL vs REST vs tRPC in 2026: Which API Style Should You Actually Use?

GraphQL vs REST vs tRPC in 2026: Which API Style Should You Actually Use?

Building an API in 2026 means choosing from at least three major paradigms: REST, GraphQL, and tRPC. Each has passionate advocates and legitimate use cases.

This isn't a "X is better" article. It's a decision framework so you can pick the right tool for your actual situation.

The Three Contenders

REST (Representational State Transfer)

The old reliable. URLs represent resources, HTTP methods express intent:

GET    /users          → list users
GET    /users/42       → get user 42
POST   /users          → create user
PUT    /users/42       → update user 42
DELETE /users/42       → delete user 42
Enter fullscreen mode Exit fullscreen mode

Maturity: Extremely high. Every language, framework, and tool speaks REST.

GraphQL

Facebook's solution to over-fetching and under-fetching. One endpoint, clients specify exactly what they need:

query {
  user(id: "42") {
    name
    email
    posts(last: 5) {
      title
      publishedAt
      tags
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Maturity: High. GraphQL is production-proven at Facebook, GitHub, Shopify, Twitter.

tRPC

End-to-end typesafe APIs using TypeScript. No schema, no code generation — just functions:

// Server
const appRouter = router({
  getUser: publicProcedure
    .input(z.object({ id: z.string() }))
    .query(({ input }) => {
      return db.users.findById(input.id);
    })
});

// Client (fully typed, no codegen needed!)
const user = await trpc.getUser.query({ id: '42' });
//    ^-- TypeScript knows the exact type!
Enter fullscreen mode Exit fullscreen mode

Maturity: Medium-high. Popular in the Next.js ecosystem, growing fast.

The Core Trade-offs

Flexibility

REST: Fixed endpoints, fixed shapes. Adding fields = versioning or breaking changes.

GraphQL: Clients request exactly what they need. Perfect for complex, evolving data requirements.

tRPC: Functions — as flexible as you want, but tied to TypeScript on both ends.

Type Safety

REST: Manual types or OpenAPI + codegen. Easy to drift.

GraphQL: Schema-driven types, but requires a build step and codegen.

tRPC: Native TypeScript — the best-in-class type safety with zero overhead.

// tRPC: this is ALL you need. No schema, no codegen.
const result = await trpc.createPost.mutate({ title: 'Hello' });
//    result is automatically typed as Post
Enter fullscreen mode Exit fullscreen mode

Performance

REST: Very cacheable (GET requests cache naturally). CDN-friendly.

GraphQL: POST-heavy, harder to cache. N+1 query problem without DataLoader. Persisted queries help.

tRPC: Similar to REST when used with HTTP transport. Good caching with React Query integration.

Learning Curve

REST     ████░░░░░░  Easy (everyone knows HTTP)
GraphQL  ████████░░  Medium-Hard (schema, resolvers, N+1, caching)
tRPC     ██████░░░░  Medium (TypeScript required, but intuitive)
Enter fullscreen mode Exit fullscreen mode

Tooling & Ecosystem

REST: Universal. Every language, every framework.

GraphQL: Great but complex — Apollo, urql, Relay on the client; Pothos, Nexus, GraphQL Yoga on the server.

tRPC: TypeScript only. Excellent Next.js integration. Growing ecosystem.

When to Use Each

Use REST when:

✅ You need a public API (consumed by third parties)
✅ Your team is polyglot (Python backend, Go service, etc.)
✅ You need aggressive HTTP caching
✅ You're building microservices that communicate across languages
✅ Simplicity is paramount
✅ You need Swagger/OpenAPI documentation out of the box
Enter fullscreen mode Exit fullscreen mode

Use GraphQL when:

✅ Multiple clients need different data shapes (mobile vs desktop)
✅ You have a complex, highly connected data model
✅ You're building a developer-facing API (like GitHub)
✅ Your team is large and schemas help coordinate frontend/backend
✅ You need real-time subscriptions built into your API layer
Enter fullscreen mode Exit fullscreen mode

Use tRPC when:

✅ You're building a full-stack TypeScript app (Next.js, Remix)
✅ You have a single team owning both frontend and backend
✅ Type safety is non-negotiable and you hate codegen
✅ You're building internal tooling or a SaaS where the API is private
✅ You want to move fast without maintaining a schema
Enter fullscreen mode Exit fullscreen mode

Real Architecture Examples

The Startup (solo dev or small team, TypeScript)

Next.js App → tRPC → Database
Enter fullscreen mode Exit fullscreen mode

tRPC wins here. Zero ceremony, maximum type safety, ships faster.

The SaaS with a Public API

Public API (REST + OpenAPI docs) → Internal service (tRPC or REST)
Enter fullscreen mode Exit fullscreen mode

Public: REST (universally consumable, documented)
Internal: tRPC or REST (team preference)

The Mobile + Web Product

iOS App    ─┐
Android App ├─→ GraphQL API → Microservices
Web App    ─┘
Enter fullscreen mode Exit fullscreen mode

GraphQL shines — each client fetches exactly what it needs.

The Enterprise Platform

Core REST API → GraphQL federation gateway → Frontend
Enter fullscreen mode Exit fullscreen mode

Combine both: stable REST contracts between teams, GraphQL at the frontend boundary.

The "Can I Use Both?" Answer

Yes, and often you should.

A common 2026 pattern:

  • REST for the public API (external integrations, webhooks)
  • tRPC for the internal full-stack app
  • GraphQL only if you have the mobile/multi-client use case

Don't choose ideology — choose by boundary:

  • External boundary → REST
  • Internal TypeScript boundary → tRPC
  • Complex multi-client data fetching → GraphQL

Quick Migration Notes

Moving from REST to tRPC:

// Before (REST endpoint)
app.get('/users/:id', async (req, res) => {
  const user = await db.users.findById(req.params.id);
  res.json(user);
});

// After (tRPC procedure)
getUser: publicProcedure
  .input(z.object({ id: z.string() }))
  .query(({ input }) => db.users.findById(input.id))
Enter fullscreen mode Exit fullscreen mode

Simpler, typed, no Express needed.

Verdict for 2026

Project Type Recommended
Full-stack TypeScript SaaS tRPC
Public API / third-party integration REST
Mobile + web with complex data GraphQL
Microservices (multi-language) REST
Internal tools at a TypeScript shop tRPC
Large product, large team GraphQL or REST

Default recommendation for a new TypeScript project in 2026: Start with tRPC. It's the fastest path to a working, type-safe API. Switch to REST or GraphQL when you have a specific reason (public API, mobile clients, polyglot team).

Conclusion

There's no universally "best" API style. There's only the right tool for your context.

tRPC is the 2026 winner for solo developers and small TypeScript teams. REST remains essential for public APIs and multi-language architectures. GraphQL earns its complexity for products with diverse clients and complex data graphs.

Choose based on your team, your clients, and your data — not based on Twitter opinions.


Building a freelance dev business? The Freelancer OS Notion Template gives you a complete CRM, project tracker, and financial dashboard — all in Notion, all free to customize.

Top comments (0)