Skip to content

Client-Server Architecture: Core Model

1.1 Responsibilities

Client and server have clear, separate responsibilities. This separation is fundamental to all web architecture.

Client responsibilities: - Render UI and handle user interactions - Manage application state (local and server-derived) - Orchestrate requests: decide when, where, and how to fetch data - Handle offline mode and optimistic updates - Cache responses to reduce network calls

Server responsibilities: - Execute business logic - Persist and query data - Authenticate and authorize requests - Enforce consistency, constraints, and validation rules - Produce stable, versioned API contracts

Why this matters: when responsibilities leak across the boundary (business logic in the client, UI state in the server), the system becomes fragile and hard to scale independently.


1.2 Communication Models

Model Protocol Direction Example
Request–response REST, GraphQL over HTTP Client initiates Fetching a user profile
RPC gRPC over HTTP/2 Client initiates Internal service call
Persistent WebSocket Both sides Chat, live dashboard
Server-push SSE (Server-Sent Events) Server only Notification stream
Streaming gRPC streaming Both sides Video feed, sensor data

Choose the model based on who initiates and how often data changes.


1.3 Transport Layer

HTTP/1.1

  • One request per TCP connection (with keep-alive: one at a time).
  • Head-of-line blocking: a slow request blocks all others on that connection.
  • Still dominant for simple REST APIs and legacy systems.

HTTP/2

  • Multiplexing: many concurrent streams share one TCP connection.
  • Header compression (HPACK): reduces repeated header overhead significantly.
  • Server push: protocol feature, but browser support is limited in modern web stacks.
  • Binary framing: more efficient than HTTP/1.1 plain-text format.
  • Used by default as the transport for gRPC.

HTTP/3

  • Runs over QUIC protocol (RFC 9000) instead of TCP.
  • QUIC is UDP-based with built-in TLS 1.3 and per-stream flow control.
  • Eliminates TCP head-of-line blocking: packet loss on one stream does not stall others.
  • Faster connection setup: 0-RTT (returning clients) or 1-RTT (new clients). By comparison, TCP requires a 3-way handshake (1 RTT), then TLS 1.3 adds another 1 RTT on top — total 2 RTT minimum before the first byte of application data is sent. QUIC merges transport and crypto into a single 1-RTT handshake.
  • Best for high-latency, lossy networks (mobile, satellite links).

TCP vs QUIC

Aspect TCP QUIC
Transport base TCP + TLS (separate) UDP + QUIC (TLS 1.3 built-in)
Head-of-line blocking Per-connection Per-stream only (no cross-stream)
Connection setup 3-way handshake + TLS 1-RTT or 0-RTT
Connection migration No — bound to IP/port 4-tuple Yes — uses Connection ID
Adoption Universal HTTP/3, modern CDNs, Nginx 1.25+

Key insight: In stable internal networks, HTTP/3 gains are often modest. The largest gains are usually seen on lossy or mobile networks.


1.4 Connection Reuse

Keep-alive (HTTP/1.1) Reuses the TCP connection for multiple sequential requests. Removes per-request TCP handshake cost, but requests still queue behind each other.

Multiplexing (HTTP/2 and HTTP/3) Multiple concurrent streams over one connection. No per-request connection cost and less blocking than HTTP/1.1. Note: HTTP/2 still runs on TCP, so packet loss at transport level can impact multiple streams; HTTP/3 reduces this with QUIC stream isolation.

Connection pooling Maintain a fixed pool of open connections to a database or upstream service. Requests borrow a connection, use it, and return it. Avoids re-handshaking on every call. Essential for any service that makes many outbound calls (e.g., API gateway, backend service).


1.5 Practical Decision Rules

Scenario Recommended transport
Public REST API, broad client support HTTP/1.1 or HTTP/2
Internal microservice RPC HTTP/2 via gRPC
Mobile clients on variable networks HTTP/3 (QUIC)
Real-time bidirectional events WebSocket
Simple server-to-client push SSE over HTTP/2
High-throughput streaming pipeline gRPC streaming over HTTP/2

Rule of thumb: use the simplest transport that meets your latency and throughput requirements. Add complexity only when measured data justifies it.