I still hear the same arguments about REST versus GraphQL that I heard in 2018, but the noise has thinned and the conversation now revolves around concrete trade‑offs.

REST with HTTP and JSON remains the lingua franca of web services; every major language and framework can spin up a REST endpoint, HTTP caching works out of the box, and status codes give you a predictable error model that most tooling expects.

GraphQL shines when you have many client flavors that need different slices of data, when your schema evolves often because adding fields never breaks existing queries, and when a domain model forces you into multiple round trips under a pure REST approach.

In my experience running an Apollo Server for a B2C product, the first version suffered from the classic N+1 problem on relational joins. Adding Facebook's DataLoader reduced the average query latency from 120 ms to about 80 ms on a 500‑request load test. The trade‑off was a modest increase in memory pressure and the need to batch across request boundaries, which forced us to introduce a short‑lived request cache. We also had to bake in persisted queries to keep the query size down for mobile networks, which added a step in our CI pipeline to validate query signatures against the schema.

For service‑to‑service traffic inside a controlled environment, gRPC with Protocol Buffers delivers noticeable latency gains thanks to binary serialization and HTTP/2 multiplexing, and the .proto contract stops accidental breaking changes from slipping into production.

When we migrated a set of internal microservices from JSON over HTTP to gRPC, we saw end‑to‑end latency drop by roughly 35 % on a 1 GB/s network. The catch was that protobuf versioning required us to maintain backward‑compatible field numbers and to ship a sidecar Envoy proxy for language‑agnostic routing. A mis‑numbered field in a .proto file caused a silent deserialization failure that took three hours to debug at 2 am because the logs only showed a generic "invalid wire type" message.

When the backend is polyglot, an API gateway can present a single REST or GraphQL façade to the outside world while routing internally to a mix of REST, GraphQL, and gRPC services; Kong, AWS API Gateway, and Azure API Management all provide that translation layer, at the cost of an extra hop and added operational complexity.

The practical checklist looks like this: if you need broad internet reach and simple caching, REST is the safe bet; if your clients request highly variable data shapes and you value schema flexibility, GraphQL pays off; if you control both ends and need raw performance, gRPC wins; the gateway sits on top when you must blend them.

Adding a gateway is not free. In our production environment Kong added about 4 ms of latency per request, mostly from TLS termination and request validation plugins. The operational burden grew as we had to manage rate‑limit policies, JWT verification, and health‑check endpoints for each downstream service. Monitoring the gateway required a separate Prometheus exporter and alerting rules to catch spikes in 5xx responses that often traced back to mis‑configured routing rules.

Take a SaaS platform that publishes public endpoints for third‑party developers; the audience spans legacy systems, mobile apps, and serverless functions, so the predictable HTTP semantics of REST keep integration friction low.

Contrast that with a mobile news app that renders dozens of widgets, each pulling a different combination of fields; a single GraphQL query can satisfy the whole screen without over‑fetching, reducing bandwidth and improving perceived speed.

My rule of thumb is to let the most demanding requirement dictate the protocol and let the rest follow; you don’t need to force every service into the same model just to keep things tidy.