bigonotes
System DesignNetworking Essentials

Application Layer Protocols

How HTTP works, and when to use REST, GraphQL, gRPC, Server-Sent Events or WebSockets for your APIs.

9 min readLast updated Networking Essentials

Layer 7 is where you spend most of your time as a developer. HTTP is the foundation, and on top of it you choose an API style: REST, GraphQL or gRPC for request-response calls, and Server-Sent Events or WebSockets when the server needs to push data. REST is the sensible default. The others earn their place when a problem has a specific need.

HTTP: the web's foundation#

HTTP is a request-response protocol: the client sends a request, the server sends one response. It is stateless, which means each request stands alone and the server doesn't need to remember earlier requests. Keeping your own services as stateless as possible is what lets you put any number of identical servers behind a load balancer.

An HTTP request has a method, path, headers and optional body; the response has a status code, headers and body

Every HTTP message has:

  1. Method (requests): what you want to do, e.g. GET, POST.
  2. Status code (responses): how it went, e.g. 200, 404.
  3. Headers: metadata such as content type, auth token or caching rules.
  4. Body: the actual content, if any.

Common methods#

Method Meaning Idempotent?
GET Read a resource. Has no body. Yes
POST Create something or trigger an action. No
PUT Replace a resource. Yes
PATCH Partially update a resource. Not necessarily
DELETE Remove a resource. Yes

Idempotent means calling it twice has the same effect as calling it once. This matters for safe retries.

Common status codes#

Range Codes
2xx success 200 OK, 201 Created
3xx redirect 301 Moved Permanently, 302 Found (temporary)
4xx client error 401 Unauthorized (not logged in), 403 Forbidden (logged in but not allowed), 404 Not Found, 429 Too Many Requests
5xx server error 500 Internal Server Error, 502 Bad Gateway (an upstream server sent a bad response)

HTTPS#

HTTPS is HTTP over TLS. It encrypts traffic so nobody between client and server can read or tamper with it. Any public website uses HTTPS without exception.

Encryption protects data in transit. It does not prove the request came from your own client. An attacker can send any body they like, so never trust it blindly.

A classic bug is reading the user ID from the request body and using it in a database query: change the ID and you can read someone else's data. You can still include IDs in requests, but the server must check them against the authenticated session or token.

REST: simple and flexible#

REST is an architectural style for building APIs on top of HTTP. HTTP is the protocol (how bytes and headers move). REST is a set of conventions for organising your API around resources.

HTTP REST
What it is A protocol A design style
Focus How messages are transmitted How resources are named and accessed
Relationship The foundation Conventions for using HTTP well

An API that follows REST's constraints is called RESTful. Modern REST APIs almost always use JSON bodies.

Endpoint Returns Request body and notes
GET /v1/users/{id} User
POST /v1/users User {"user_name": "alex"} (server assigns the id)
PUT /v1/users/{id} User {"user_email": "alex@example.com"}
GET /v1/users/{id}/posts [Post] Nested resource: a user's posts

Think in resources, not actions. updateUser and startGame are operations, not resources. The RESTful versions are PUT /users/{id} and PATCH /games/{id} with {"status": "started"}.

When to use it: by default. REST isn't the fastest option for very high-throughput internal traffic, because JSON is a fairly inefficient format to serialize and parse. But most applications aren't bottlenecked by serialization, and REST is well understood, easy to debug and works everywhere. A common split is REST for public APIs and gRPC for hot internal paths.

GraphQL: flexible data fetching#

GraphQL is a query language for APIs. With REST the server decides the shape of each response. With GraphQL the client writes a query listing exactly the fields it wants, and the server returns that shape.

It solves three problems:

  1. Under-fetching: a page needs data from several endpoints, so it makes several round trips.
  2. Over-fetching: endpoints return far more than the page needs "just in case", so responses are slow and heavy.
  3. Endpoint sprawl: writing a new endpoint for every new page.
query {
  user(id: "42") {
    name
    posts(last: 5) { title }
    followers { totalCount }
  }
}

One request returns the name, the last five post titles and the follower count, instead of calling /user, /posts and /followers.

Core value Clients get exactly what they need, nothing more
Best for Mobile apps and complex frontends where many teams share the same data
Analogy REST is a set menu chosen by the server. GraphQL lets the client pick from a buffet.
Costs Harder to cache at the HTTP layer; a careless query can trigger many database calls (the N+1 problem)

When to use it: when frontend requirements change often or are deliberately vague, or when an app is slow because of too many API round trips.

gRPC: efficient service-to-service calls#

gRPC is an open-source RPC (remote procedure call) framework originally built at Google. It lets one service call a function on another as if it were local. It combines two pieces:

  • Protocol Buffers (Protobuf): a compact binary format for data, defined in a .proto schema.
  • HTTP/2: a transport that can carry many requests at once over a single connection.

Why binary is faster#

  • JSON is text. To read {"id": 123} the computer scans for braces and quotes and converts the characters 1, 2, 3 into a number. That costs CPU.
  • Protobuf doesn't send field names. It sends a small numeric tag and the raw value, which is quick to decode and much smaller on the wire.

The result is less CPU and bandwidth per call, which lowers both latency and cost at high traffic.

Features worth knowing#

  • Strong typing: both sides generate code from the same .proto file, so sending a string where an integer is expected fails at build time, not in production.
  • Multiplexing: many calls share one HTTP/2 connection without blocking each other.
  • Streaming: the server, the client or both can stream messages, useful for logs or live feeds.
REST (JSON) gRPC (Protobuf)
Readability Human-readable, easy to debug Binary, needs tools to inspect
Schema Loose Strict .proto contract
Performance Slower (text parsing) Faster (binary)
Best for Public APIs, browsers, third-party developers Internal microservices, high-throughput service-to-service calls

When to use it: internal calls inside your data centre where throughput and latency matter. Avoid it for public APIs: browsers don't support it natively, and external developers find it harder to use. Using REST everywhere is still a fine starting point, and you can move hot paths to gRPC later.

Web server vs API server#

Two kinds of server sit at layer 7, and they do different jobs.

Web server API server
Goal Deliver the UI to people Deliver data to programs
Content Static files: HTML, CSS, JavaScript, images Dynamic data, usually JSON
Serves The browser directly Mobile apps and single-page apps (React, Vue)
Examples nginx, Apache Flask, FastAPI, Django REST Framework (Python)

Pushing data to the client#

Plain request-response means the client has to ask. When the server needs to send updates as they happen, you have three main options.

Comparison of polling, Server-Sent Events and WebSockets: polling repeats requests, SSE keeps one response open for server pushes, WebSockets carry messages both ways

Server-Sent Events (SSE)#

  • An HTTP standard for the server to push data over one long-lived response that never quite finishes.
  • The server writes messages to the stream over time, and the client handles each one as it arrives.
  • Browsers support it natively through the EventSource API, which makes it a good fit for public web apps.
  • Automatic reconnection: if the connection drops, EventSource reconnects and sends the ID of the last message it received, so the server can resume.
  • Real-world headaches: load balancers and proxies may close long-lived connections, and some networks buffer the stream, which delays messages. Plan for reconnects and heartbeats.
  • Use for: one-way, low-latency updates such as live auction prices, stock tickers and notifications.

WebSockets#

  • Two-way: client and server can both send messages at any time over a persistent connection.
  • Starts as HTTP: the client sends an HTTP request asking to "upgrade". Because of this, cookies and headers from the HTTP request are available during setup.
  • Then raw TCP: after the upgrade, the WebSocket owns the TCP connection until one side closes it. There's no required message format, so you can send JSON or binary.
  • Every hop must support it: load balancers, proxies and firewalls in the path all need WebSocket support.
  • Stateful: each server holds open connections for its users, which makes scaling to millions of users harder (see Load Balancing for the usual pub/sub fix).
  • Use for: high-frequency two-way interaction like chat and multiplayer games. For simple request-response or one-way pushes it is overkill.

Choosing: a summary#

Each protocol has a situation where it is the natural choice.

Protocol When to use it Why Example
REST Public APIs, typical web apps, general service calls Simple, works in every browser, easy to test A URL shortener: POST a long URL, GET link info
gRPC Internal microservices where speed matters Binary format saves CPU and bandwidth Checkout service calling a fraud-detection service thousands of times a second
GraphQL Frontends with complex, changing data needs One round trip, exactly the fields needed A profile page needing name, recent posts and follower count
SSE One-way updates from server to client Plain HTTP, auto-reconnect, simpler than WebSockets Stock ticker, live sports score
WebSockets Frequent two-way real-time messages Both sides send instantly over one connection Chat with typing indicators, multiplayer games

A common real-world mix: REST for external users, gRPC between internal services, and SSE or WebSockets only for the specific live features that need them. Choose based on the requirement, not on what is fashionable.

Key takeaways#

  • HTTP is stateless request-response: method, status code, headers and body.
  • HTTPS encrypts the pipe but doesn't make the request trustworthy. Always validate identity server-side.
  • REST is the default API style. Model resources, not actions.
  • GraphQL fixes over- and under-fetching for complex frontends, at the cost of caching and query-cost complexity.
  • gRPC (Protobuf over HTTP/2) is the fast, strictly typed choice for internal services.
  • Use SSE for one-way push and WebSockets for frequent two-way messages.

Found a mistake? Tell me on LinkedIn ↗

Further reading#