Client-Server Model
Session 1.1 · ~5 min read
The Foundation of Networked Computing
Nearly every application you use today follows the same structural pattern: one process asks for something, another process provides it. The asker is the client. The provider is the server. This separation of roles is the client-server model, and it has shaped how we build software since the 1960s.
Your browser is a client. When you type a URL and press Enter, it sends a request to a server. The server processes that request, retrieves or computes the appropriate data, and sends back a response. That exchange, from request to response, is the fundamental unit of interaction in networked systems.
Client-Server Model: An architecture in which a client initiates requests and a server fulfills them. The client and server are separate processes, often running on separate machines, communicating over a network using a defined protocol.
The Request-Response Cycle
Every HTTP interaction follows a predictable sequence. The client opens a connection to the server, sends a request containing a method (GET, POST, PUT, DELETE, etc.), a target resource (the URL path), headers (metadata about the request), and optionally a body (the data payload). The server reads the request, performs the work, and sends back a response containing a status code (200 OK, 404 Not Found, 500 Internal Server Error, etc.), headers, and optionally a body.
This cycle repeats for every interaction. Loading a single web page might trigger dozens of request-response cycles: one for the HTML document, several for CSS and JavaScript files, more for images, and additional ones for API calls that fetch dynamic data.
The key property of HTTP, as defined in RFC 7230, is that each request-response pair is an independent transaction. The server does not inherently remember anything about previous requests from the same client. This is what we mean by statelessness.
Stateless vs. Stateful Interactions
HTTP is a stateless protocol by design. Each request carries all the information the server needs to fulfill it. The server does not retain any memory of previous interactions between requests. This simplifies server implementation enormously: any server in a cluster can handle any request, because no request depends on what happened before.
But users expect continuity. When you log in to an application, you expect to stay logged in as you navigate between pages. When you add items to a shopping cart, you expect them to still be there when you visit the checkout page. These expectations require state, meaning data that persists across multiple request-response cycles.
This creates a tension. The protocol is stateless, but the application needs to be stateful. Resolving this tension is one of the core challenges in web application architecture.
| Dimension | Stateless | Stateful |
|---|---|---|
| Server memory | No request context retained between calls | Server tracks client context across requests |
| Scalability | Easy. Any server can handle any request. | Harder. Client must reach the same server, or state must be shared. |
| Reliability | Server crash loses nothing. Client retries freely. | Server crash may lose session data. |
| Complexity | Simpler server logic | Requires session storage, replication, or sticky routing |
| Example | DNS lookup, static file serving, REST API call | Shopping cart, user login session, WebSocket connection |
| Bandwidth | May be higher (client resends context each time) | Lower per-request (context stored on server) |
Session Management Strategies
When an application needs state on top of a stateless protocol, it must use a session management strategy. There are several approaches, each with distinct trade-offs.
1. Server-Side Sessions with Cookies
The most traditional approach. When a user logs in, the server creates a session object in memory (or in a database) and assigns it a unique session ID. This ID is sent to the client as a cookie via the Set-Cookie header, as specified in RFC 6265. On every subsequent request, the browser automatically includes this cookie. The server looks up the session ID, retrieves the stored state, and processes the request with full context.
The advantage is simplicity and security: the actual session data never leaves the server. The disadvantage is that the server must store and manage session data. In a multi-server deployment, either all servers must share a session store (e.g., Redis), or the load balancer must route the same client to the same server (sticky sessions).
2. Token-Based Authentication (JWT)
JSON Web Tokens take a different approach. Instead of storing state on the server, the server encodes the session data (user ID, permissions, expiration time) into a signed token and hands it to the client. The client includes this token in the Authorization header of every request. The server validates the token's signature and extracts the session data without touching any session store.
This approach scales well because any server can validate the token independently. But it introduces new challenges: tokens cannot be easily revoked once issued, and they increase the size of every request. If a token is stolen, the attacker has access until it expires.
3. Client-Side Storage
For non-sensitive state, applications can store data directly in the client using localStorage, sessionStorage, or cookies. Shopping cart contents, user preferences, and UI state are common candidates. This eliminates server-side storage entirely for that data, but the client cannot be trusted. Any data stored client-side can be inspected and modified by the user.
4. Hybrid Approaches
Most production systems combine strategies. A JWT handles authentication (who you are), server-side sessions handle authorization context (what you can do right now), and client-side storage handles UI preferences. The choice depends on security requirements, scalability needs, and how much trust you place in the client.
Systems Thinking Lens
The client-server model is a system with feedback loops. Server load affects response time. Response time affects user behavior. User behavior affects request volume, which feeds back into server load. A slow server causes users to retry, which increases load, which makes the server slower. This is a reinforcing feedback loop, the same concept from Session 0.4.
Session management adds another dimension. Stateful servers introduce coupling between the client and a specific server instance. This coupling constrains how you scale, how you handle failures, and how you deploy updates. Every architectural decision in this space creates downstream constraints on the rest of the system.
Understanding these trade-offs is not about memorizing which approach is "best." It is about recognizing that each choice shifts the balance of complexity, security, and scalability in predictable ways.
Further Reading
- RFC 7230: HTTP/1.1 Message Syntax and Routing. The specification that defines HTTP's request-response model and its stateless nature.
- RFC 6265: HTTP State Management Mechanism. The specification for cookies, the primary mechanism for adding state to HTTP.
- MDN: Using HTTP Cookies. A practical guide to how cookies work in browsers, including security attributes.
- Wikipedia: Client-Server Model. Historical context and variations of the architecture.
Assignment
Open your browser's developer tools (F12 or Ctrl+Shift+I) and go to the Network tab. Navigate to any website you use regularly. Watch the requests appear.
- Identify 3 different requests in the list. For each one, note the method (GET/POST), the URL, and the status code.
- Click on each request and look at the Request Headers. Does the request carry a
Cookieheader? Does it carry anAuthorizationheader? If it carries neither, it is a stateless request. If it carries either, it is transporting session state. - For requests that carry session state, determine the strategy: is it a session cookie (short opaque string) or a JWT (long Base64-encoded string with two dots)?
Write down your findings. You have just traced how a real application manages the tension between a stateless protocol and stateful user experience.