Backend ServicesBy Abdul Rahman26 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.

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.
Pick 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.


