Module 11 · Architectural patterns · Lesson 1 of 9
Client-server architecture
The shape underneath almost everything: clients ask, servers answer, state lives on the server. Thin versus thick clients, the tiers that grew out of it (presentation, application, data), statelessness as the key to horizontal scale.
Why it matters
Every system design interview starts with a box labelled client and a box labelled server, and the quality of the answer depends on knowing what that arrow commits you to. Client-server is not a legacy pattern; it is the default from which monoliths, microservices and serverless all derive, and its central discipline, keep servers stateless and state in a data tier, is what makes horizontal scaling possible at all.
The idea
In client-server architecture, many clients (browsers, mobile apps, other services) send requests to a server that holds the shared state and logic and returns responses. The client is responsible for presentation and interaction; the server for business rules, data and coordination. The separation lets clients be numerous, heterogeneous and untrusted while the server is few, controlled and authoritative.
Tiers
The two-tier form (client talks directly to a database) died because clients could not be trusted with credentials or business rules. Three-tier separates presentation (the client), application (servers with the logic) and data (databases and caches). N-tier adds layers such as an API gateway, a service layer or an integration tier. The tiers are a deployment and trust boundary as much as a code organisation: each can scale, secure and fail independently.
Thin and thick clients
| Thin client | Thick (rich) client | |
|---|---|---|
| Where logic lives | Server renders and decides; client displays | Client holds significant logic and state; server is an API |
| Examples | Server-rendered web pages, terminals | Single-page apps, mobile apps, desktop software |
| Pros | Simple clients, easy updates, one place for rules | Responsive interaction, offline capability, less server load per interaction |
| Cons | Every interaction is a round trip; server does all the work | Logic duplicated across platforms; must re-validate everything server-side; harder to update |
Modern web apps are thick clients talking to APIs, which is why API design and authentication occupy whole modules of this track. The rule that survives either choice: the server validates and authorises everything, because the client is untrusted.
Statelessness: the scaling discipline
An application server that keeps a user's session, shopping cart or partial computation in its memory can only serve that user from that machine. Sticky load balancing patches over this and breaks on failure and deploys. The discipline is to make application servers stateless: every request carries what it needs (a session token, an idempotency key) and all durable state lives in the data tier (database, cache, object store). Then any server can serve any request, servers can be added or replaced freely, and the hard problems of state are concentrated where the previous stage's lessons address them.
Where the model strains
Many clients needing real-time updates strains request-response; the Communication patterns module adds push. Huge numbers of simple lookups strain a single data tier; caching and replication relieve it. The server as a single trust and control point becomes a bottleneck for very large or very distributed systems; peer-to-peer (later in this module) distributes the role. And a server that grows to hold every feature becomes the monolith of the next lesson, with its own strengths and limits.
Trade-offs
Client-server buys a clear trust boundary, central control of logic and data, and simple reasoning about where things happen, and pays with the server tier being the scaling and availability focus and every interaction being a network round trip. Statelessness in the application tier is the single choice that keeps the model scalable; violating it is the most common early architectural mistake.
In an interview
Draw it and say the discipline: "Clients, a load balancer, stateless application servers, and a data tier with the database and cache. Servers hold no session state, so we scale by adding instances and failures just reroute. All authorisation is server-side because clients are untrusted." Thirty seconds, and it sets up every later decision.
Check yourself
An application stores each user's shopping cart in the memory of the server that handled their first request, and uses sticky sessions to route them back. During a deploy, users lose their carts. What is the architectural fix?