SD System Design In Depth
0%
lesson system-designscalingapihttp

HTTP, REST, and gRPC

Module 3.1: Network Protocols & Service Communication Updated Sep 17, 2026
📄 Cheat Sheet
gRPC vs REST: Why Isn’t Everyone Using gRPC?
ArjanCodes gRPC vs REST: Why Isn’t Everyone Using gRPC? Watch on YouTube ↗

A balanced, practical comparison that covers Protocol Buffers, HTTP/2, code generation, browser support and debugging cost, and explains why REST remains the default for public APIs.

0:00 / --:--

Under the Hood: Serialization Formats & Wire Protocols

Selecting between REST (typically JSON over HTTP/1.1 or HTTP/2) and gRPC (Protocol Buffers over HTTP/2) is fundamentally a trade-off between human readability/client reach and binary serialization throughput/CPU efficiency.

Wire Format Comparison: JSON vs Protocol Buffers

flowchart LR subgraph JSONWire ["Textual JSON Payload (High CPU & Wire Overhead)"] J1["{ user_id: 98412, email: [email protected], active: true }"] JNote["Field names repeated on wire; text parsing requires memory allocation and string decoding."] end subgraph ProtoWire ["Binary Protocol Buffers (Compact Serialization)"] P1["[08 8C 80 06 12 0E 61 6C 69 63 65...]"] PNote["Field names replaced by integer tags and varints. Typically 2x-5x smaller than JSON and cheaper to parse."] end

Protocol Mechanics: HTTP/1.1 vs HTTP/2 in gRPC

  • Head-of-Line Blocking: In HTTP/1.1, a single TCP connection processes one request-response pair at a time. Concurrency requires opening multiple TCP sockets (typically 6 per browser host). gRPC runs over HTTP/2, where binary frames are multiplexed concurrently across a single persistent TCP connection.
  • Schema Enforcement: REST over JSON relies on optional runtime validators (JSONSchema). gRPC uses strictly typed .proto files compiled into typed language bindings at build time, catching many type mismatches at compile time (proto3 default values, unknown fields and version skew between services can still cause runtime surprises).
  • Bidirectional Streaming: gRPC natively supports client streaming, server streaming, and bidirectional streaming over HTTP/2, making it ideal for live sensor telemetry and real-time backend synchronization.

When to Use Which?

FeatureREST (JSON over HTTP/1.1 / HTTP/2)gRPC (Protobuf over HTTP/2)
Payload EncodingHuman-readable ASCII text / UTF-8Compact, binary-encoded varints
Parsing SpeedModerate to slow (string scanning & memory allocations)Fast (binary decoding, no text scanning; standard libraries still allocate)
Browser SupportNative across 100% of browsers and devicesRequires gRPC-Web proxy translation layer
Ideal Use CasePublic APIs, mobile apps, third-party integrationsHigh-throughput East-West internal microservices

Worked example: the same message in JSON and Protobuf

A user record {"user_id": 98412, "email": "[email protected]", "active": true} is 56 bytes as compact JSON (61 with the spaces shown). With a Protobuf schema int64 user_id = 1; string email = 2; bool active = 3; the encoding is:

  • user_id: 1 tag byte plus a 3 byte varint for 98412, 4 bytes.
  • email: 1 tag byte, 1 length byte, 14 bytes of text, 16 bytes.
  • active: 1 tag byte plus 1 value byte, 2 bytes.

Total 22 bytes, about 2.5 times smaller. Most of the saving comes from not repeating field names. The string content is identical in both, so text-heavy messages shrink much less, and with gzip applied to both formats the gap narrows further. Parsing is usually faster for Protobuf because it avoids text scanning and number parsing, but standard Protobuf libraries still allocate objects; zero-copy decoding is a property of formats such as FlatBuffers and Cap'n Proto.

HTTP versions in one table

VersionTransportConcurrency on one connectionHead-of-line blocking
HTTP/1.1TCPOne request at a time (pipelining exists but is effectively unused)At the HTTP layer; browsers open about 6 connections per host to compensate
HTTP/2TCPMany multiplexed streamsRemoved at the HTTP layer, but one lost TCP packet stalls all streams
HTTP/3QUIC over UDPMany independent streamsA lost packet stalls only the streams whose data it carried

Choosing

SituationPreferWhy
Public API for third partiesREST with JSON and OpenAPIUniversal tooling, curl-friendly, HTTP caching
Browser front endREST or GraphQLNative browser support
High-volume internal service callsgRPCGenerated typed clients, compact encoding, deadlines built in
Streaming between servicesgRPC streamingClient, server and bidirectional streams are first class
Cacheable reads at a CDNREST GETURLs and cache headers work with every cache

Operational gotchas

  • Load balancing gRPC: HTTP/2 keeps one long-lived connection, so an L4 load balancer pins all of a client's calls to one backend. Use L7 (per-request) balancing or client-side balancing.
  • Schema evolution: never reuse a Protobuf field number; mark removed numbers as reserved.
  • Debuggability: binary payloads need tools like grpcurl and server reflection.
Check yourself Question 1 of 3
Counting Protobuf bytes apply
From: Worked example: the same message in JSON and Protobuf

Using the lesson's encoding rules, a message has int64 id = 1 set to 150 (a 2-byte varint) and string name = 2 set to "bob". How many bytes is the Protobuf encoding?

Key Takeaways

gRPC uses Protocol Buffers to achieve significantly smaller wire payloads and lower CPU serialization overhead than JSON. Typical savings are around 2-5x before compression, and less for text-heavy messages or after gzip.
HTTP/2 multiplexing allows gRPC to stream multiple requests concurrently over a single TCP connection.
Use REST for public browser-facing APIs and third-party reach; use gRPC for high-performance internal microservices.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue