Back to Blog
EngineeringOctober 24, 202613 min read

REST vs gRPC: When to Use Each, Plus Protobuf vs JSON

gRPC inside your system, REST at the edge, a queue when nobody waits. A decision table on payload size, speed, streaming and gRPC-Web browser limits, built from the official docs.

REST vs gRPC: When to Use Each, Plus Protobuf vs JSON

11 min read · Last updated: October 24, 2026

REST vs gRPC, when to use each: use gRPC with Protocol Buffers for internal service-to-service calls where you control both ends and need speed, strict contracts or streaming. Use REST with JSON for public and browser-facing APIs. Use async messaging like Kafka when the caller should not wait for the answer at all.

Came here from Instagram, LinkedIn, X or YouTube? Here is the full source list you came for. Everything below is built from these, nothing else.

The gRPC docs and specs

The Protocol Buffers docs

The standards

The alternatives

The benchmark

Here is the decision in one line. gRPC inside your system, REST at the edge, a message queue when nobody needs to wait.

Most teams argue about this as if it were one choice. It is two. The first is the API style: REST (resources over HTTP) or gRPC (remote procedure calls over HTTP/2). The second is the data format: JSON (text) or Protocol Buffers (binary). gRPC uses Protobuf by default and REST usually uses JSON, but you can mix them.

Key takeaways

  • The value 150 in a Protobuf field takes 3 bytes on the wire. The same field as JSON, {"a":150}, takes 9 bytes.
  • In Auth0's 2017 benchmark between two Java services, Protobuf requests took 78% less time than JSON uncompressed, and were 6 times faster compressed (25ms vs 150ms).
  • In browsers with compression on, the same benchmark found Protobuf only 9% smaller and 4% faster.
  • gRPC supports 4 call types, including bidirectional streaming. gRPC-Web in the browser supports only 2: unary and server streaming.
  • Protobuf's own docs say to consider something else for data that exceeds a few megabytes.

REST vs gRPC vs Protobuf vs JSON: the comparison table

The table compares the two pairings you will actually choose between: REST with JSON and gRPC with Protobuf. Every row comes from the docs and specs in the source list.

REST + JSONgRPC + Protobuf
TransportAny HTTP versionHTTP/2 framing
PayloadText, field names repeated in every messageBinary, only field numbers on the wire
Example size{"a":150} = 9 bytes08 96 01 = 3 bytes
ContractOptional (OpenAPI if you add it)Required .proto file, code generated
StreamingRequest and response, plus SSE or WebSockets on the sideUnary, server, client and bidirectional streaming built in
Browser supportNative, every browserNeeds gRPC-Web, unary and server streaming only
DebuggingReadable in curl or DevToolsNeeds the .proto to decode a message
ErrorsHTTP status codesgrpc-status sent in HTTP/2 trailers, even on success
TimeoutsYou build themDeadlines are part of the protocol
Best forPublic APIs, browsers, partners, webhooksInternal service-to-service calls, polyglot backends, streaming

Is gRPC faster than REST?

Usually yes for service-to-service calls, but most of the gain comes from Protobuf being smaller and faster to parse than JSON, plus HTTP/2 running many requests over one connection. In Auth0's 2017 benchmark between two Java services, Protobuf requests took 78% less time than JSON. In browsers with compression on, the gap shrank to 4%.

There are two separate speed wins. Keep them apart.

The format. Protobuf's overview describes it as "like JSON, except it's smaller and faster." JSON repeats every field name as text in every message. Protobuf sends a field number and a compact value, so the parser does less work.

The transport. RFC 9113, the HTTP/2 standard published in June 2022, says HTTP/2 reduces latency "by introducing field compression and allowing multiple concurrent exchanges on the same connection." gRPC is specified on HTTP/2 framing, so every gRPC call gets that. REST can run on HTTP/2 too, which narrows this part of the gap.

Now the honest part. The Auth0 numbers measure Protobuf vs JSON over plain HTTP between Spring Boot apps, not gRPC vs REST end to end. The test sent 500 GET requests carrying 50,000 Person records between two DigitalOcean machines. Real APIs usually send much less. For single-record POST requests, the same benchmark found message sizes "effectively the same" and Protobuf only 4% faster.

If speed is your reason to switch, measure your own payloads first.

Protocol Buffers vs JSON: size and speed

Protocol Buffers is smaller than JSON because it never sends field names, only a field number, a wire type and a compactly encoded value. One integer field set to 150 is 3 bytes in Protobuf and 9 bytes as JSON. The cost is readability: you cannot interpret a Protobuf message without its .proto schema.

Here is the exact example from the Protobuf encoding guide. The schema:

syntax = "proto3";

message Test1 {
  int32 a = 1;
}

Set a to 150 and serialize it. The guide shows the bytes:

08 96 01

08 means "field 1, varint." 96 01 is 150 as a varint, where each byte carries 7 bits of value and 1 bit that says "more bytes follow." The name a never appears. Compare JSON:

{"a":150}

That is 9 bytes. Rename the field to accountBalance and the JSON grows. The Protobuf stays at 3 bytes.

JSON has its own fine print. RFC 8259, the JSON standard from December 2017, says integers are only reliably interoperable between -(2^53)+1 and (2^53)-1. That is why ProtoJSON, Protobuf's official JSON mapping, emits 64-bit integers as strings "to ensure no precision loss." If you send large database IDs as JSON numbers, this will bite you.

Protobuf's docs are also clear about where it does not fit. From the "When Is Protobuf Not a Good Fit?" section:

  • "For data that exceeds a few megabytes, consider a different solution."
  • "Messages are not compressed." You can gzip them like any file.
  • "You cannot fully interpret one without access to its corresponding .proto file."
  • "Protobuf is not a formal standard of any organization." JSON is an IETF standard.

Can gRPC be used in the browser?

Not directly. Browsers do not expose the HTTP/2 framing gRPC needs, so you use gRPC-Web, a separate protocol. Classic gRPC-Web needs a proxy such as Envoy in front of your gRPC server and supports only unary and server-streaming calls. Client streaming and bidirectional streaming do not work in the browser.

The gRPC-Web spec gives the reason: it has to "decouple from HTTP/2 framing which is not, and will never be, directly exposed by browsers." So it moves the trailers, where gRPC puts its status code, into the response body.

The grpc-web README lists the limits:

  • It "currently supports 2 RPC modes": unary and server-side streaming.
  • Server streaming works "Only when grpcwebtext mode is used," the base64 text format.
  • The binary grpcweb mode supports unary calls only.
  • "Client-side and Bi-directional streaming is not currently supported."
  • Clients "connect to gRPC services via a special proxy," with Envoy as the default. Nginx, Apache APISIX and a Go proxy also work.

There is a second route. Connect, a set of libraries for Protobuf APIs, supports "gRPC, gRPC-Web, and Connect's own protocol" and serves gRPC-Web "without relying on a translating proxy like Envoy." Its own protocol runs over HTTP/1.1 and HTTP/2 and accepts both JSON and binary Protobuf. If you want one .proto file to serve your backend and your frontend, start there.

If your frontend only needs plain request and response, REST with JSON is still the shortest path. For another RPC-style option in the browser, see my breakdown of Cap'n Web, Cloudflare's RPC library.

When should I use gRPC?

Use gRPC when you own both the client and the server, they talk often, and you want a strict contract, generated clients in several languages, streaming, or lower latency. Skip it for public APIs, third-party integrations and anything a browser calls directly, where REST with JSON is simpler to adopt and debug.

The gRPC strengths that matter day to day:

  1. The contract is the code. One .proto file generates typed clients and servers. A renamed field breaks the build, not production.
  2. Streaming is built in. The core concepts page lists four method types: unary, server streaming, client streaming and bidirectional streaming.
  3. Deadlines are built in. gRPC "allows clients to specify how long they are willing to wait for an RPC to complete." In a chain of five services, that stops one slow call from hanging everything.
  4. Many calls, one connection. HTTP/2 multiplexing means a chatty service does not open a new connection per request.

The REST strengths gRPC does not replace:

  1. Anyone can call it. curl, a browser, Postman, a partner's PHP script. No code generation.
  2. You can read it. A JSON response in DevTools explains itself.
  3. HTTP status codes. Caches, load balancers and monitoring tools already understand them. New to this? Start with REST APIs explained for beginners.

Kafka messages vs REST calls between services

Use REST or gRPC when the caller needs an answer right now to continue, like checking a price before checkout. Use Kafka, the open-source event streaming platform, when the caller only needs to announce that something happened and other services react later, like "order placed." A slow consumer never blocks the producer.

The Kafka introduction describes producers and consumers as "fully decoupled and agnostic of each other." That is the core difference. A REST call fails if the other service is down. A Kafka event waits in the topic until the consumer comes back.

Two details from the Kafka docs shape most designs:

  • "Events are not deleted after consumption." Each topic keeps events for a retention period you configure, so a new service can replay history.
  • Events with the same key go to the same partition, and consumers read a partition "in exactly the same order as they were written." Ordering is per partition, not per topic.

Most real systems use both. Checkout calls payments synchronously, then publishes an event that email, analytics and inventory consume on their own time. This trade-off comes up constantly in system design interviews, and the deciding question is always whether the caller has to wait.

GraphQL vs gRPC for microservices

GraphQL and gRPC solve different problems. GraphQL is a query language that lets a client, usually a frontend, ask for exactly the fields it needs in one request. gRPC is for fast, typed calls between backend services. A common pattern uses both: GraphQL at the edge for the UI, gRPC between the services behind it.

The GraphQL docs define it as "a query language for your API, and a server-side runtime for executing queries using a type system you define for your data." Its strength is that a client can "receive just that data in the expected shape with a single request." That matters for a mobile screen that would otherwise call five REST endpoints.

For many services, GraphQL offers federation, "composing services into a unified schema." That is a gateway job. Service-to-service traffic still wants the fixed contract and low overhead of gRPC.

REST vs gRPC: when to use each, by situation

Pick by who calls the API and whether they wait for the result. This is the table I would use.

Your situationPickWhy
Public API for outside developersREST + JSONAnyone can call it, no code generation
Browser calls your backend, plain request and responseREST + JSONNative in every browser, readable in DevTools
Browser needs live updates from the servergRPC-Web, Connect, or REST + SSEgRPC-Web supports server streaming in text mode
Browser needs client or bidirectional streamingWebSocketsgRPC-Web does not support these modes
Internal services in several languagesgRPC + ProtobufOne .proto, generated typed clients
High-volume internal calls where latency mattersgRPC + ProtobufSmaller payloads, HTTP/2 multiplexing, deadlines
One service announces an event, many react laterKafka or another message brokerProducer never waits, events can be replayed
A frontend needs data from many services at onceGraphQL at the edge, gRPC behind itClient picks fields, backend keeps strict contracts
Payloads larger than a few megabytesStream files or use object storageProtobuf's docs say to consider a different solution
Small team, one backend, one frontendREST + JSONThe extra tooling does not pay for itself yet

One warning. Teams often adopt gRPC "because it is faster," then spend a month on proxies, codegen pipelines and decoding binary payloads. Pick gRPC for the contract and the streaming. Treat the speed as a bonus.

FAQ

Is gRPC always faster than REST?

No. gRPC tends to win on large or frequent internal calls because Protobuf is compact and HTTP/2 multiplexes requests. For small payloads the gap shrinks: in Auth0's 2017 benchmark, single-record POST requests were effectively the same size and Protobuf was only 4% faster. Measure your own traffic before switching.

Can I use Protocol Buffers with REST?

Yes. Format and API style are separate choices. You can send binary Protobuf over a normal HTTP endpoint, which is what the Auth0 benchmark did between two Spring Boot apps. Protobuf also has an official JSON mapping, ProtoJSON, so one schema can serve binary and JSON clients.

Should a startup use gRPC from day one?

Usually not. With one backend and one frontend, REST with JSON is faster to build, debug and hand to new developers. Add gRPC when several internal services talk constantly, you need streaming, or you want generated clients across languages.

Pick the one internal call in your system that runs most often and measure it before you rewrite anything, then use the free tools on Art of Code to format and inspect the JSON you send today. If you are rethinking how your internal APIs report errors too, read why your private API doesn't need HTTP status codes.

Written by Adithya Guttha, Founder of Art of Code.

#rest api#grpc#protocol buffers#microservices#api design

Sign in to like and save posts.

Curious Adithya

Written by

Curious Adithya

@curious_adithya · 5 followers

Discussion

Comments (0)

Want to join the conversation?

Sign in to comment

No comments yet. Be the first to comment!