System Design Protocols: REST, RPC, and TCP/UDP
How do servers talk to each other? This guide explains the key protocols: REST vs RPC for APIs, TCP vs UDP for transport.
Abstract AlgorithmsMore actionsโ
Reading progress
17 min left
Metadata and pacingโ
Total read
17 min
Sections
19
โด On this pageโ
โฃ Need another angle?โ
Switch the article companion into a lower-complexity framing, then quiz yourself when you are ready.
1. Overview
How do servers talk to each other? This guide explains the key protocols: REST vs RPC for APIs, TCP vs UDP for transport.
Why it matters
TLDR: ๐ฏ Use REST (HTTP + JSON) for public, browser facing APIs where interoperability matters.
Show high-level concept flowโ
๐ The Protocol Stack: What Talks to What
Starting point
๐ REST vs. gRPC: The API Protocol Showdown
Next concept
โ๏ธ How REST Actually Works: Request โ Response
Next concept
๐ง Deep Dive: How Protobuf Binary Encoding Works
Next concept
โก How gRPC Works: Contracts and Binary Efficiency
Outcome
At a glance
System lens
See System Design Protocols: REST, RPC, and TCP/UDP as a living topology.
How do servers talk to each other? This guide explains the key protocols: REST vs RPC for APIs, TCP vs UDP for transport.
๐ The Protocol Stack: What Talks to What
Ingress and assumptions
๐ REST vs. gRPC: The API Protocol Showdown
State transition
โ๏ธ How REST Actually Works: Request โ Response
State transition
๐ง Deep Dive: How Protobuf Binary Encoding Works
State transition
โก How gRPC Works: Contracts and Binary Efficiency
Outcome and guarantees
Narrative transition
Move from explanation to operating judgment.
Use these checkpoints as the conceptual pacing layer before continuing into the full article.
!Why this matters
TLDR: ๐ฏ Use REST (HTTP + JSON) for public, browser facing APIs where interoperability matters.
#Key section to watch
Pay attention to "๐ REST vs. gRPC: The API Protocol Showdown"; it usually contains the main mechanism or tradeoff.
?Interview angle
Be ready to explain ๐ The Protocol Stack: What Talks to What and ๐ REST vs. gRPC: The API Protocol Showdown with one concrete example and one tradeoff.
Tradeoff path 1
๐ The Protocol Stack: What Talks to What: speed-first
TLDR: ๐ฏ Use REST (HTTP + JSON) for public, browser facing APIs where interoperability matters.
Tradeoff path 2
๐ REST vs. gRPC: The API Protocol Showdown: reliability-first
Choose gRPC (HTTP/2 + Protobuf) for internal microservice communication when latency counts.
Failure rehearsal
Pressure-test the mental model.
๐ The Protocol Stack: What Talks to What misunderstood
Low latency does not automatically mean high throughput under contention.
Mitigation: Revisit ๐ The Protocol Stack: What Talks to What and validate the first principles.
Risk 68%
๐ REST vs. gRPC: The API Protocol Showdown tradeoff missed
Eventual consistency does not mean random correctness; it depends on reconciliation strategy.
Mitigation: Compare against ๐ REST vs. gRPC: The API Protocol Showdown and document the tradeoff.
Risk 58%
Back to the article
Continue into the authored sections with the topology in mind: each heading should now answer what changes, what can fail, and what guarantee the system is trying to preserve.
TLDR: ๐ฏ Use REST (HTTP + JSON) for public, browser-facing APIs where interoperability matters. Choose gRPC (HTTP/2 + Protobuf) for internal microservice communication when latency counts. Under the hood, TCP guarantees reliable ordered delivery; UDP trades reliability for speed. Know which layer you're operating at and pick the right tool for each job.
๐ The Protocol Stack: What Talks to What
gRPC โ Google's Remote Procedure Call framework โ transfers the same payload as REST in 60โ80% fewer bytes by using binary Protobuf encoding instead of verbose JSON text. For a service handling one million RPCs per second, that compression gap is roughly the difference between $12,000 and $20,000 per month in bandwidth costs. Protocol choice is a real engineering and business decision, not a stylistic preference.
To see the gap concretely, consider a simple User object. A REST/JSON payload for that object includes every field name as a human-readable string in every message โ roughly 56 bytes for id, name, and email combined. The equivalent gRPC/Protobuf message encodes the same data in approximately 21 bytes, because field names are defined once in the .proto schema file and never sent over the wire โ only compact numeric tags identify each field. At 1M requests/second, that 35-byte-per-message difference adds up to over 2.5 TB of saved bandwidth every day.
Before choosing a protocol, it helps to know where it lives in the network stack. Every call crosses multiple layers, each with its own trade-offs. The application layer is where REST, gRPC, GraphQL, and WebSocket live โ it defines how data is structured and interpreted. Below that, the transport layer is where TCP, UDP, and QUIC operate, governing reliability and ordering of packet delivery. Underneath everything, the network layer handles routing via IP.
REST and gRPC are application-layer protocols built on top of TCP. They define how data is structured and interpreted. WebRTC for video calls uses UDP at the transport layer for lower latency. Understanding this layering tells you which problems each protocol can and cannot solve.
๐ REST vs. gRPC: The API Protocol Showdown
These are the two dominant choices for service-to-service communication.
| Feature | REST (HTTP/1.1 or HTTP/2 + JSON) | gRPC (HTTP/2 + Protobuf) |
| Message format | JSON (human-readable text) | Protobuf (binary, compact) |
| Schema | Optional (OpenAPI) | Required (.proto contract) |
| Browser support | Native | Needs a proxy (grpc-web) |
| Streaming | Limited (SSE, polling) | First-class (server, client, bidirectional) |
| Payload size | Larger (verbose JSON) | 3โ10x smaller (binary) |
| Code generation | Optional | Automatic (stubs from .proto) |
| Debugging | Easy (curl, browser DevTools) | Harder (need specialized tools) |
| Best for | Public APIs, external integrations | Internal microservices, high-throughput RPC |
The rule of thumb: if you control both ends of the connection and throughput matters, use gRPC. If third parties or browsers need to call your service, REST is the safer default.
โ๏ธ How REST Actually Works: Request โ Response
A REST API treats everything as a resource identified by a URL. You act on resources using HTTP verbs. A GET on /users/42 fetches that user; a POST to /users creates a new one; PUT replaces the entire resource at a given URL; PATCH applies a partial update; and DELETE removes it. The HTTP response includes a status code (200 OK, 404 Not Found, 500 Internal Server Error) and usually a JSON body.
What makes a REST API "RESTful":
- Stateless โ the server doesn't remember previous requests
- Uniform interface โ consistent URL patterns and verb semantics
- Cacheable โ GET responses can be cached by intermediaries
A well-designed REST API is self-documenting: the URL tells you the resource, the verb tells you the action.
๐ REST Request Lifecycle
sequenceDiagram
participant C as Client
participant LB as Load Balancer
participant API as API Server
participant DB as Database
C->>LB: GET /users/42 (HTTPS)
LB->>API: Route to available server
API->>DB: SELECT * WHERE id=42
DB-->>API: User row
API-->>LB: 200 OK {id:42, name:"Alice"}
LB-->>C: 200 OK {id:42, name:"Alice"}
Note over C,LB: GET is cacheable (Cache-Control)
C->>LB: POST /users {name:"Bob"}
LB->>API: Route to server
API->>DB: INSERT INTO users ...
DB-->>API: New id=43
API-->>LB: 201 Created Location:/users/43
LB-->>C: 201 Created Location:/users/43
This diagram shows two complete REST request lifecycles โ a GET for an existing resource and a POST to create a new one โ passing through a load balancer, API server, and database. Notice the 200 response for the GET versus the 201 Created response with a Location header for the POST. The key HTTP semantics to take away: GET is idempotent and cacheable, POST is not idempotent and always creates a new resource; these distinctions determine how clients, load balancers, and CDNs are allowed to cache and retry requests automatically.
๐ง Deep Dive: How Protobuf Binary Encoding Works
Protobuf serializes each field as a compact (field_number, wire_type) tag followed by the value. Field names are never sent over the wire โ only numeric tags defined in the .proto file. A string "hello" in JSON is 7 bytes; in Protobuf it is 5 bytes plus a 1-byte tag. For messages sent millions of times per day, this 3โ10ร size reduction translates directly into bandwidth savings and lower serialization latency.
| Format | Sends field names? | Self-describing? | Relative payload size |
| JSON | Yes (as strings) | Yes | Baseline |
| Protobuf | No (field numbers only) | No (.proto required) | 3โ10ร smaller |
โก How gRPC Works: Contracts and Binary Efficiency
gRPC starts with a Protobuf schema (.proto file) that defines services and message types. A service definition declares each RPC method by name, specifying its request type and return type โ for example, a GetUser unary call that takes a user ID and returns a User message, or a ListUsers server-streaming call that returns a sequence of User messages over a single connection. Message types declare each field with a name, a scalar type (int32, string, bool, etc.), and a unique field number. That field number โ not the name โ is what travels over the wire.
From this schema, gRPC auto-generates client and server stubs in your language of choice. The client calls userService.GetUser(id) like a local function โ the network call is transparent.
Why Protobuf is faster than JSON:
- Binary encoding:
42as a 4-byte int, not the 2-byte ASCII string "42" - No key repetition per record (field numbers are 1-byte tags)
- Schema-aware: no need to re-parse field names on every deserialization
gRPC streaming types:
| Type | Direction | Use case |
| Unary | Client sends one, server replies one | Standard request/response |
| Server streaming | Client sends one, server replies many | Real-time updates, log streaming |
| Client streaming | Client sends many, server replies one | File upload, batch ingestion |
| Bidirectional streaming | Both stream simultaneously | Chat, collaborative editing |
๐ TCP vs. UDP: The Transport Layer Choice
REST and gRPC both run over TCP. But some workloads need to go lower and choose the transport layer directly.
TCP (Transmission Control Protocol):
- Establishes a connection (3-way handshake before data flows)
- Guarantees every packet arrives and arrives in order
- Automatically retransmits lost packets
- Flow control prevents fast senders from overwhelming slow receivers
- Higher overhead, but correctness is automatic
UDP (User Datagram Protocol):
- No connection setup โ just fire packets and hope
- No delivery guarantee, no ordering guarantee
- No retransmission โ dropped packets are gone
- Minimal overhead: ideal when speed matters more than completeness
| Use case | TCP | UDP |
| Web pages, APIs | โ | โ |
| File transfer | โ | โ |
| Video streaming | Sometimes | โ (RTP over UDP) |
| Online gaming (position updates) | โ too slow | โ |
| DNS lookup | Sometimes TCP | โ (small, fast) |
| VoIP | โ retransmit delay is worse than loss | โ |
Why live video uses UDP: if a video frame is late, retransmitting it is pointless โ by the time it arrives, it's already behind. A dropped frame is better than a frozen screen from TCP's retransmit-and-wait behavior.
๐ TCP 3-Way Handshake
sequenceDiagram
participant C as Client
participant S as Server
Note over C,S: Connection establishment
C->>S: SYN (seq=100)
S-->>C: SYN-ACK (seq=200, ack=101)
C->>S: ACK (ack=201)
Note over C,S: Connection established
C->>S: GET /api/data (payload)
S-->>C: 200 OK + response body
Note over C,S: Connection teardown
C->>S: FIN (seq=300)
S-->>C: ACK (ack=301)
S->>C: FIN (seq=400)
C-->>S: ACK (ack=401)
This diagram walks through the full TCP session lifecycle: a three-message SYN/SYN-ACK/ACK handshake establishes the connection, data flows in both directions, and a four-message FIN/ACK/FIN/ACK exchange tears it down. For REST and gRPC calls, this handshake cost is amortised when HTTP keep-alive reuses the connection across multiple requests โ but for short-lived connections it adds one full round-trip before any application data is sent. This overhead is one of the key motivations for HTTP/2 multiplexing and QUIC's zero-RTT connection establishment.
๐ WebSockets: Persistent Bidirectional TCP
REST is request-response: the client asks, the server answers. But what if the server needs to push data to the client without being asked?
WebSockets upgrade an HTTP connection to a persistent, full-duplex channel. Once the handshake completes, both sides can send messages independently at any time.
sequenceDiagram
Client->>Server: HTTP Upgrade: websocket
Server-->>Client: 101 Switching Protocols
Server-->>Client: {"event": "price_update", "value": 142.50}
Client->>Server: {"action": "subscribe", "symbol": "AAPL"}
Server-->>Client: {"event": "price_update", "value": 143.10}
Use cases: live stock tickers, chat applications, collaborative editing, real-time dashboards, multiplayer games.
๐ Protocol Decision Flow
Use this flowchart to select the right protocol for each service boundary in your system.
flowchart TD
A[New Service Interface] --> B{External or public-facing?}
B -->|Yes| C[REST + JSON over HTTPS]
B -->|No| D{Need real-time streaming?}
D -->|Server push to browser| E[WebSocket]
D -->|Internal bidirectional| F[gRPC bidirectional streaming]
D -->|No streaming needed| G{Latency and throughput critical?}
G -->|Yes| H[gRPC + Protobuf over HTTP/2]
G -->|No| C
Choose the outermost layer first: if external clients or browsers need access, REST is the safest default. For internal high-throughput paths, gRPC's binary encoding reduces payload size by 3โ10ร compared to JSON.
๐งช Practical Protocol Selection Checklist
This checklist translates the REST-vs-gRPC-vs-UDP decision framework from the protocol sections into a concrete set of diagnostic questions you answer for each service boundary in your system. It was structured as a per-protocol checklist because the most common mistake is picking a single protocol for an entire application โ in practice, a well-designed system uses different protocols at different layers. As you work through each section, answer honestly: if your answers for the gRPC block are all "yes," that boundary is a genuine gRPC candidate; if even one answer is "no," the tooling overhead may not be justified by the throughput gain.
For REST:
- Is the API public or consumed by third-party developers? If yes, REST wins on discoverability.
- Do you need HTTP caching through CDN or proxies? REST GET responses are cacheable by default.
- Will browser clients call this API directly? REST is natively supported without a proxy.
For gRPC:
- Do you control both the client and server? gRPC requires shared
.protocontracts. - Is payload size or serialization latency a bottleneck? Protobuf is 3โ10ร more compact than JSON.
- Do you need streaming (server push, client upload, or bidirectional chat)? gRPC has first-class support.
For UDP/QUIC:
- Does a dropped packet expire before a retransmit would arrive? Live video and gaming frames do.
- Do you need minimal connection setup overhead? QUIC establishes connections in one round-trip.
Apply the checklist per service pair, not per application. A single system often uses REST for its public API, gRPC internally, and WebSockets for a real-time dashboard.
๐ Real-World Applications: Real-World Protocol Choices at Scale
Twitter/X internal RPC: Uses a combination of HTTP APIs for external clients and internal Thrift (a REST-like binary protocol) for microservice-to-microservice calls.
Netflix internal APIs: Originally REST; migrated critical paths to gRPC for the efficiency gains at hundreds-of-millions-of-requests/day scale.
YouTube video streaming: Uses UDP-based QUIC (a newer transport protocol from Google) which gives them TCP-like reliability guarantees with UDP-like connection setup speed. QUIC eliminates TCP's head-of-line blocking problem for multiplexed streams.
โ๏ธ Trade-offs & Failure Modes: Protocol Trade-offs
- REST verbosity vs. simplicity: JSON is easy to debug with
curlor browser DevTools, but verbose at scale โ large payloads raise bandwidth costs and serialization latency on hot paths. - gRPC tooling overhead:
.protoschema management andgrpc-webproxies for browsers add operational burden. Debugging binary traffic requires specialized reflection tools rather than a quick browser inspection. - UDP packet loss is silent: Dropped UDP packets are gone with no error. Applications that silently skip lost frames must handle partial state carefully to avoid subtle data integrity bugs.
- WebSocket connection storms: WebSockets hold persistent TCP connections. A rolling deploy that restarts servers simultaneously drops all connections, and clients reconnecting concurrently create a thundering-herd spike on the backend.
๐งญ Decision Guide: Protocol Selection by Use Case
| Scenario | Protocol choice | Reasoning |
| Public API for third-party developers | REST + JSON | Universally accessible, easy to document |
| Internal microservices, high-throughput | gRPC + Protobuf | Binary efficiency, strong typing, streaming |
| Real-time push from server to browser | WebSocket | Persistent bidirectional channel |
| Live video, gaming, VoIP | UDP-based (RTP, QUIC) | Latency beats reliability for these workloads |
| IoT devices on lossy networks | MQTT over TCP | Lightweight pub/sub, designed for constrained devices |
| Cross-service event streaming | Kafka (TCP-based) | Persistent, replay-able, high-fanout |
๐ ๏ธ REST HTTP Semantics: How Status Codes and Headers Enforce Constraints
Every HTTP framework exposes the same REST semantics through its response API: status codes, Location headers, ETag fingerprints, and Cache-Control directives. Understanding why each choice matters is more important than the specific framework used to apply them.
A GET request is both safe (no side effects) and idempotent (calling it a thousand times changes nothing on the server). This means clients, CDNs, and proxies are allowed to cache, retry, and prefetch GET responses automatically. An ETag โ a fingerprint of the resource's current version, often derived from a database row version โ enables conditional GET requests: if the client sends back the ETag from its cached copy, the server can respond with a lightweight 304 Not Modified (no body) instead of a full 200 with payload. This is REST's stateless caching constraint working across an entire infrastructure tier without any coordination.
A POST is not idempotent: each call creates a new resource with a new identity. The correct response is 201 Created with a Location header pointing to the URL of the newly created resource. This combination tells clients and proxies definitively that the request succeeded, where to find the result, and that they must not auto-retry POST calls the way they can retry GET calls.
A PUT is idempotent: it replaces the entire resource at a known URL. Sending the same PUT request twice leaves the server in exactly the same state both times, so networks can safely retry it after a timeout without risk of duplication โ unlike POST, where a retry would create a second resource.
Three REST constraints visible in this framework:
| HTTP property | Demonstrated by | Why it matters |
| Safe + idempotent (GET) | If-None-Match / 304 conditional response | Enables transparent caching at every layer without coordination |
| Not idempotent (POST) | 201 + Location header on creation | Clients and proxies know they must not auto-retry; the response reveals where the resource is |
| Idempotent (PUT) | Full replacement returning 200 | Networks can safely retry after timeouts โ re-sending the same PUT is harmless |
For a full deep-dive on Spring Boot REST, content negotiation, and HATEOAS, a dedicated follow-up post is planned.
๐ ๏ธ gRPC in Practice: Schema-First Binary Communication
The gRPC workflow starts with a .proto schema file that acts as the authoritative API contract between services. The schema declares the service name, each RPC method with its request and response types, and every message's fields with their numeric tags. This schema is compiled by the protoc tool and language-specific gRPC plugins to generate type-safe client stubs and server skeleton classes โ eliminating the manual JSON parsing, URL routing, and HTTP verb selection that REST requires.
On the server side, developers implement the generated service interface by overriding each RPC method. For a unary call like GetUser, the method receives the typed request object and writes a single response back through a stream observer, after which it signals completion. For a server-streaming call like ListUsers, the implementation writes multiple response messages to the stream one by one before closing it โ all over the same underlying HTTP/2 connection, with no additional connection setup cost per message.
On the client side, the generated blocking or async stub exposes each RPC as a typed method call. The client calls stub.getUser(request) and receives a typed User object back โ no URL construction, no JSON deserialization, and no HTTP status code parsing. The network details are fully encapsulated by the generated stub.
The .proto file is the contract that both sides compile against โ a breaking change to the schema (removing a field, changing a type) causes a compile error in both client and server code, enforcing the versioning discipline described in the Lessons section. Adding a new optional field with a new field number is a backward-compatible change; removing or renumbering a field breaks any client or server still expecting the old layout.
For a full deep-dive on gRPC service design, streaming patterns, and error handling, a dedicated follow-up post is planned.
๐ Lessons from Protocol Choices in Production
Engineering teams that have operated distributed systems at scale share consistent protocol lessons.
Avoid premature gRPC adoption: gRPC's tooling overhead (.proto management, grpc-web proxies for browsers, reflection for debugging) is significant. Start with REST and migrate the hot paths to gRPC once you have measured the latency impact.
Design for protocol versioning from day one: REST APIs should include a version prefix (/v1/). gRPC services should reserve field numbers in .proto files. Retroactive versioning is painful.
UDP is not "faster REST": UDP eliminates TCP's reliability guarantees entirely. Only use it when stale data is genuinely preferable to delayed data โ live game positions, sensor telemetry, or video frames.
Instrument the transport layer: track p99 request latency, payload size, and connection error rates per protocol. Teams often discover that HTTP/1.1 keep-alive was disabled, eliminating the assumed benefit of persistent connections.
๐ TLDR: Summary & Key Takeaways
- REST = stateless, resource-oriented, universally compatible โ use it for public APIs and external integrations.
- gRPC = binary, contract-driven, streaming-capable โ use it for internal high-throughput RPC.
- TCP = reliable, ordered, connection-based โ the default for anything where correctness matters.
- UDP = unreliable, low-overhead, connectionless โ use it when a dropped packet is better than a delayed one.
- WebSockets give you a persistent full-duplex channel on top of TCP for real-time bidirectional communication.
- Protocol choice is a trade-off between developer ergonomics, latency, bandwidth, and ecosystem compatibility.
Expandable deep dives
๐ The Protocol Stack: What Talks to Whatโ
Dive deeper into this section and cross-reference concepts before moving to the next heading.Jump to section
๐ REST vs. gRPC: The API Protocol Showdownโ
Dive deeper into this section and cross-reference concepts before moving to the next heading.Jump to section
โ๏ธ How REST Actually Works: Request โ Responseโ
Dive deeper into this section and cross-reference concepts before moving to the next heading.Jump to section
๐ REST Request Lifecycleโ
Dive deeper into this section and cross-reference concepts before moving to the next heading.Jump to section
Key takeaways
- โTLDR: ๐ฏ Use REST (HTTP + JSON) for public, browser facing APIs where interoperability matters.
- โChoose gRPC (HTTP/2 + Protobuf) for internal microservice communication when latency counts.
- โUnder the hood, TCP guarantees reliable ordered delivery; UDP trades reliability for speed.
- โKnow which layer you're operating at and pick the right tool for each job.
Test Your Knowledge
Ready to test what you just learned?
AI will generate 4 questions based on this article's content.
Reader feedback
Was this article useful?
Rate it before you leave, then follow or subscribe for the next deep dive.
Continue learning

Written by
Abstract Algorithms
@abstractalgorithms
Related deep dives

