Yashveer Singh
Connect
<- All posts
Backend, APIs, and System Design6 min read

REST vs GraphQL vs gRPC: A Decision Matrix for Founders

REST, GraphQL, and gRPC are API design paradigms that determine how clients and servers communicate. REST uses HTTP methods and resource URLs with JSON responses, following the constraints of the web architecture. GraphQL is a query language where clients specify exactly what data they need in a single request, reducing over-fetching and under-fetching. gRPC uses Protocol Buffers over HTTP/2 for strongly typed, high-performance communication between services, primarily used for internal service-to-service communication. The choice between them is primarily determined by who the API clients are and what the communication requirements are.

Written by Yashveer Singh, founder of Yashveer Labs.

What you need to know

  • REST is the right default for public APIs, external integrations, and APIs where clients are not controlled by the same team. It is universally understood.
  • GraphQL is the right choice for data-heavy frontend applications where over-fetching and multiple round trips are affecting performance or developer productivity.
  • gRPC is for internal service-to-service communication where performance and type safety matter more than human-readability.
  • Mixing all three in one application is common and often correct. Each paradigm serves different client types and communication patterns.
  • Choosing GraphQL for a CRUD API where the data model is simple is over-engineering. Choose based on the actual data fetching requirements.

The core argument

The REST vs GraphQL debate is usually not a technical argument; it is a preference argument where the choice is rationalized after the fact. Teams that prefer GraphQL find evidence that it solves over-fetching. Teams that prefer REST find evidence that GraphQL is complex to cache and secure. Both sides are correct: GraphQL does solve over-fetching, and it is harder to cache and secure than REST. The question is which trade-off matches the specific application's requirements.

The decision matrix is simpler than most blog posts make it: who are the clients, and what are the data fetching patterns? For a public API that external developers will integrate against: REST. The tooling (OpenAPI, Postman, Swagger UI), the developer familiarity, and the caching infrastructure all favor REST for public APIs. For a data-heavy frontend application with complex and variable data dependencies: GraphQL. The frontend team can fetch exactly what they need without coordinating with the backend team for new endpoints. For internal services in a microservices architecture that need to communicate efficiently across language boundaries: gRPC.

The implementation cost matters too. REST is the cheapest to implement correctly; every backend developer knows it, every HTTP framework supports it natively, and the tooling is mature. GraphQL has a steeper initial implementation cost (schema design, resolver implementation, N+1 query handling) but pays back through frontend velocity on complex data requirements. gRPC requires Protocol Buffer familiarity and the generated code workflow, which is unfamiliar to developers who have not used it before.

Common mistakes

  1. Choosing GraphQL to solve performance problems that are actually backend problems. If the API is slow because queries are not indexed or the business logic is inefficient, GraphQL does not fix the underlying performance. GraphQL reduces network round trips and data transfer, which helps for network-constrained clients, but it does not make slow resolvers fast.
  1. Not implementing DataLoader for GraphQL N+1 queries. GraphQL's resolver model naively produces N+1 queries: a query for a list of users that also requests each user's orders makes one database query for users and N queries for orders. DataLoader batches these requests into a single query per type per execution. Implementing GraphQL without DataLoader (or a similar batching solution) produces performance that is worse than the REST API it replaced.
  1. Using gRPC for client-facing APIs without a transcoding proxy. Browsers cannot make direct gRPC calls because HTTP/2 frames in the browser environment do not match gRPC's framing. gRPC-Web is a workaround, but it adds implementation complexity. For client-facing APIs, REST or GraphQL are the appropriate choices. gRPC belongs in the internal service mesh.
  1. Not using OpenAPI for REST APIs. A REST API without an OpenAPI specification has no machine-readable contract. This means manual documentation, no client SDK generation, and no request validation. Adding OpenAPI specification (either code-first with a library like tRPC or swagger-jsdoc, or design-first) is worth the investment for any API that external clients or other teams consume.
  1. Implementing pagination differently across endpoints in a REST API. REST APIs that use cursor pagination for some endpoints, offset pagination for others, and a custom scheme for yet others create inconsistent client integration work. Define a pagination convention across the API (cursor-based is more scalable than offset) and apply it consistently.

Where to start

  1. Identify who the API clients are. List every client: web frontend, mobile app, external integrations, internal services. For each client, identify whether they need flexible data fetching (favors GraphQL), need a stable public interface (favors REST), or need high-performance internal communication (favors gRPC). The client inventory determines the right paradigm.
  1. For a new SaaS product: start with REST. REST is the most productive starting point for a team building a new product quickly. It is universally understood, well-tooled, and correct for most API use cases. Consider GraphQL specifically when the frontend team expresses concrete pain with over-fetching or multiple round trips in the current REST implementation.
  1. Write the API specification before writing implementation code. For REST: write an OpenAPI spec. For GraphQL: write the schema. For gRPC: write the .proto file. The specification is the contract between client and server. Writing it first surfaces design issues (ambiguous resource relationships, missing operations) before implementation begins and makes the API design a deliberate decision.

Related reading

FAQ

Frequently asked

Author

The reason I write these

I write these because the writing is the proof. Yashveer Singh, founder of Yashveer Labs. The systems I build are not theoretical. They are running right now, serving real users, generating real revenue. That is the bar I hold this writing to. If you want to hire someone who can match that bar, I am the call.

Related reading