Client-Server Architecture: The Model Every System Design Builds On
Client server architecture explained: how the client server model works, stateless vs stateful servers, and the request response cycle, the contract behind every system design on this site.
Vertical vs horizontal scaling priced how the server side grows; latency vs throughput priced the conversation itself; the availability, reliability, and durability definitions set what a running service owes; CAP theorem and consistency models priced the truth the server keeps. All four describe machines that already speak one grammar; this article is that grammar. The distributed systems article called this arrangement the smallest example of a distributed system and the one everything else extends; this is that arrangement, drawn properly.
The cast is two roles, not two machines. A client is any program that initiates: a browser, a mobile app, another service calling yours, a cron job fetching a config file. A server is any program that listens for requests and produces answers. What separates the roles is who speaks first, and the separation is a contract: the client promises to ask in a format the server understands, the server promises to answer in a format the client can parse, and neither needs to know how the other is built. That contract is the whole model. It is why a phone from one decade can talk to a datacenter from another, and why the microservices architecture debate is not about whether to keep the model (services are simply clients and servers of each other) but about how many of them to run.
The model won for one structural reason: it draws a line (the network) and puts the interface exactly on it. Everything behind the line can be replaced, upgraded, scaled, or balanced without any client noticing, which is precisely what load balancing in system design exists to exploit. The alternatives lose on that same line: a mainframe with terminals keeps the smarts and the screens welded together, and peer-to-peer pushes coordination into every node, which is why distributing work is hard even before you add scale. Client-server centralizes answerability (one side owns the data and the truth) while keeping the other side thin, replaceable, and everywhere.
The model is not free, and this article will price it rather than worship it. Every answer costs a round trip; the server side concentrates data, traffic, and failure; and the client-speaks-first rule means a server cannot initiate, the bend in the model that websockets and push strategies exist to fix. What follows defines the model and its contract, walks one request through the full flow, then takes the two decisions that follow from it: where state lives, and what each trip around the request response cycle costs.
What is client server architecture
Client server architecture is a model in which programs divide into two roles connected by a network: a client that initiates requests, and a server that listens for them, processes them, and sends responses back. The two sides share a contract (a request format and a response format) and neither side needs to know how the other is built.
Three things make that definition precise. First, client and server are roles, not machines; one laptop can play both at once, a browser acting as a client to a web service and as a server to a local debugging tool. Second, the relationship is asymmetric by design: clients know addresses; servers know nothing about who will call. A server waits in the dark for anyone holding its address and speaking its dialect. Third (the part that turns the diagram into an architecture) the contract is the interface: HTTP with its methods and status codes, DNS with its question-and-answer, a database’s wire protocol with its queries and result sets. Fix the contract and the sides decouple; versioning becomes a negotiation instead of a rebuild.
The contract has teeth because both sides police it. A server that changes its response shape breaks clients it has never heard of, which is why APIs are versioned, why deprecated fields linger for years, and why the API gateway exists as a place to translate between generations of the contract. The model’s history is largely the story of contracts hardening: from FTP’s ad-hoc rules to HTTP’s strict grammar to TLS’s pinned handshakes, every layer added is a promise made more explicit, and therefore a promise the other side can finally rely on.
How does the client server model work
The cleanest way to see the model in motion is to follow one request through its whole life. The cast: a browser (the client), a web server behind a load balancer (the server side), and a request for a page. Six numbered steps, each of which can fail, and each of which a different part of the stack owns.
- Resolve. The client turns the hostname into an IP address by asking DNS: itself a client-server exchange, the model bootstrapping the model.
- Connect. The client opens a TCP connection to that address and, for HTTPS, runs the TLS handshake: certificates checked, keys agreed, the line made private.
- Write the request. The client sends a method, a path, headers, and an optional body; GET and a route, plus cookies, auth tokens, and the metadata the contract requires.
- Process. The server parses the request, routes it, and does the work; reading a cache, querying a database, or calling another service, which makes that service a client too.
- Respond. The server writes back a status code, headers, and a body: 200 and the page, or 404 and an apology, or 500 and a stack trace nobody asked for.
- Reuse or release. The connection either returns to a pool for the next request or closes: a small decision with real latency consequences, priced two sections down.
What the flow hides is how much of it can fail: DNS can lie, the connection can be refused, the request can be dropped mid-flight, the server can be slow, the response can be wrong, the connection can die before the answer lands. Every failure mode a client-server system has lives somewhere on that path, which is why the health checks, timeouts, and retry with exponential backoff machinery that manages the path get their own articles. The model is simple; the space around it is not.
Stateless vs stateful
Stateless means every request carries all the context the server needs to answer it: who is asking (an auth token), what they want (the path and body), and everything else besides. The server holds no memory of past conversations; ask it the same question twice and it processes both as if it had never met you. Stateful means the opposite: the server remembers. It knows this is your tenth visit, which step of your checkout you were on, which tiles of your board are flipped. That memory (the state) has to live somewhere, and where it lives decides almost everything about how the system scales.
Statelessness is the property that makes servers replaceable, and replaceable is what makes horizontal scaling cheap. If any server can answer any request, a load balancer can spread traffic across any number of them; a dead server becomes a non-event (the balancer simply stops sending it traffic) and deploys roll instead of halting the world. HTTP was built stateless on purpose for exactly this reason: the web’s servers were expected to fail, be replaced, and be added constantly, and a protocol that remembered its callers would have made all three impossible.
“Stateless” never means the system has no state; it means the state moved. Authentication becomes a token the client re-presents on every request; shopping carts move into a database; session preferences move into a store the whole fleet can reach, which is why distributed caching exists, and why state that must stay consistent across servers pays the CAP theorem tax. The state does not vanish; it relocates from one server’s memory to somewhere the next server can also find. That relocation is the real design work (and the real cost) hiding behind the word “stateless.”
Statefulness earns its keep when the connection is the point. Database sessions hold state on both ends; a WebSocket pins a conversation to one server’s memory; game servers, streaming connections, and anything with server-side progress are stateful by nature. The honest pattern is not “never stateful” but “stateful deliberately, in one place, with a plan for the server dying”: sticky routing so a client returns to the server that remembers it, or replicated state so the memory is not one machine’s to lose. The failure mode is accidental state; a server that should be stateless quietly remembering, and breaking the moment the balancer moves it.
Request response cycle
At the application layer, the request response cycle has a grammar. A request states a method (GET to read, POST to create, PUT and PATCH to replace and edit, DELETE to remove) plus a path, a set of headers, and an optional body. A response answers with a status code in five families (1xx informational, 2xx success, 3xx redirection, 4xx the client’s fault, 5xx the server’s) plus headers of its own. The codes are the contract’s error vocabulary: a well-behaved client treats 429 and 503 differently from 500, because one says “later, politely” and the other says “nobody is home.” Methods also carry a promise of repetition safety; GET twice is the same GET; POST twice is two orders, the seed of idempotency as a design discipline.
Every cycle costs a round trip, and the round trip has anatomy. The client pays DNS lookup, TCP connect, and TLS handshakes before any payload moves; then the network charges its round-trip time, the server charges its processing, and the response pays the network again. The latency vs throughput article prices this properly (the tail is what users feel) but the structural point belongs here: a cycle-heavy design is a latency-paying design, and the fee is charged per conversation. Ten sequential round trips to render one page will always lose to one round trip that brings the whole page, which is why chatty protocols are refactored into batched ones, and why “we’ll just call the API three times” is a phrase that ages badly under load.
The cycle’s cheapest optimization is to stop paying setup costs twice. HTTP keep-alive holds a connection open across cycles, saving the TCP and TLS handshakes; HTTP/2 goes further, multiplexing many cycles over one connection so requests queue behind each other instead of beside each other; and client-side connection pools keep warm connections ready so cycles skip setup entirely. Each shaves fixed costs off the top of every request, and each was invented because the raw model, one fresh connection per cycle, was too expensive to leave alone. The cycle is the model’s heartbeat; the ecosystem around it is mostly pacemakers.
The cycle has one structural limitation, and it is worth naming precisely: the server cannot start a cycle. It can only answer one. Anything the server needs to say unprompted (a new message, a price change, a move in a game) has to be smuggled through the client’s next question, held open until there is something to say, or sent over a connection that upgraded past the cycle entirely. That bend is the subject of the next article on the reading spine; the model’s one unbreakable rule, and the entire reason the real-time stack exists on top of it rather than inside it.
Common mistakes
- Treating “stateless” as “no state.” The state never disappears; it moves to tokens, databases, and shared stores, and someone has to design where. Teams that skip that design rediscover it as stale sessions and carts that lose items. The word describes the server’s memory, not the system’s.
- Sticky state on one server behind a balancer. Round-robin traffic onto servers that keep session memory in-process breaks every other login. Either the balancer pins the client to its server, or the state moves to a store; picking neither is not an option; it is an outage scheduled for the first deploy.
- Assuming the cycle is free. Every request response cycle charges connect, network, and processing, and cycle-heavy designs pay it multiplied. The fix is almost always structural: batch the calls, cache the answers, or stop asking three questions when one suffices.
- One server, no redundancy. The model concentrates answerability, which is also a concentration of failure. One server is a single point of failure with a friendly name; the fix, a load balancer plus a second node, is the cheapest high availability money buys.
- Confusing “client” with “browser.” Browsers are one species of client; services calling services are clients too. Teams that design auth, rate limits, and versioning only for browsers get surprised when their own backend (the biggest client they have) breaks the assumptions. The model does not care who initiates; the design must not either.
FAQ
What is client server architecture in simple terms?
A client is a program that asks; a server is a program that answers; the contract between them lets both change independently. Everything else (DNS, load balancers, proxies, caches) exists to make the asking and answering faster, safer, or spread across more machines.
Is client server architecture the same as microservices?
No. Microservices is an arrangement made of the model: each service is a server to those that call it and a client to those it calls. The microservices architecture question is how many boundaries to draw, not whether the client-server contract stays; it always does.
What is the difference between stateless and stateful servers?
A stateless server answers from the request alone; every piece of context travels with it. A stateful server answers from memory of past requests. Stateless servers are interchangeable and scale horizontally; stateful servers own their callers’ history and need sticky routing or replicated state to survive their own failures.
Is HTTP the only client server protocol?
No; DNS, SMTP, IMAP, FTP, and every database wire protocol are client-server contracts too. HTTP is the web’s dialect and the one most infrastructure is built around, but the model is protocol-agnostic: if one side initiates and the other answers, the model applies.
What are the main disadvantages of client server architecture?
Three honest ones. Every answer costs a round trip, which compounds into latency for chatty designs. The server side concentrates traffic, data, and failure, one fleet to protect and scale. And the server cannot initiate: real-time updates need workarounds built on top of the model rather than inside it.
Related articles
- Next read: what are websockets; the model’s one broken rule, fixed: a persistent connection where the server can speak first, when the request response cycle stops fitting the workload, this is where the design goes next.
- vertical vs horizontal scaling, what happens when the server side of the model outgrows one machine: the growth paths and the price of each.
- latency vs throughput; the vocabulary every round trip is measured with: p99, tail latency, and why the slowest request is the one users remember.
- what is a distributed system; the map this model sits at the corner of: partial failure, no shared memory, and why “the smallest example” still counts as a distributed system. Every term in this article is a corner of that map.
- microservices architecture, the model grown up: services as clients and servers of each other, and the trade-off ledger for drawing that many boundaries. Read it once the two-role grammar here feels automatic.
Last updated on 12 September 2026