WhollySoftware
Back to blogBackend

Choosing Between REST, GraphQL, and gRPC for Internal Services

Wholly Software TeamMarch 14, 20258 min read
Choosing Between REST, GraphQL, and gRPC for Internal Services

REST is still our default for anything client-facing — mobile apps, third-party integrations, public APIs. It's the format most partner engineering teams already understand, it caches well at the HTTP layer, and debugging it doesn't require special tooling beyond curl and a browser. For a client's partner-facing order API, REST with clear resource semantics and standard status codes was the right call precisely because it's boring and well understood.

GraphQL earned its place on a project with a mobile app team and a backend team that kept getting into fights over endpoint shape — the mobile team wanted a single call that returned a product with its variants, pricing, and inventory in one nested response, and REST kept forcing either over-fetching or a proliferation of purpose-built endpoints. GraphQL let the client specify the shape it needed, and it cut mobile app payload sizes by around 40% on the product detail screen alone.

The cost of GraphQL showed up in caching and N+1 query risk. Without DataLoader-style batching, a naive resolver for nested fields turned one client request into dozens of database queries. We had to build batching into every resolver that touched a relation, which added real implementation time relative to REST's straightforward per-endpoint query.

gRPC is what we reach for between internal services that we control on both ends — a recommendation service calling an inventory service, for example, where both are written in-house and latency matters more than human readability. Protobuf's binary encoding and HTTP/2 multiplexing gave us a measurable latency improvement over JSON-over-REST for high-frequency internal calls, on the order of single-digit milliseconds per call, which adds up when a request fans out to six internal services.

The trade-off with gRPC is tooling friction — you can't just curl it, you need generated clients and protobuf compilation in the build pipeline, and it's a harder sell for anyone outside the immediate team. We only use it where the caller and callee are both under our control and the traffic volume justifies the extra build complexity. For anything crossing a team or company boundary, we still default to REST.

API DesignGraphQLgRPCMicroservices
Choosing Between REST, GraphQL, and gRPC for Internal Services — Wholly Software