Skip to main content

Command Palette

Search for a command to run...

Understanding HTTP from First Principles

Why the Web Works, Why HTTP Is Stateless, and Why That Was a Brilliant Decision

Published
19 min read
Understanding HTTP from First Principles
S

Software developer with a strong foundation in React, Node.js, PostgreSQL, and AI-driven applications. Experienced in remote sensing, satellite image analysis, and vector databases. Passionate about defense tech, space applications, and problem-solving. Currently building AI-powered solutions and preparing for a future in special forces.

Every backend engineer uses HTTP. APIs, mobile apps, microservices, and they all "speak" it. Yet, most us learn HTTP as a list of status codes and methods to memorize.

That approach misses the point. HTTP is not just a protocol; it is a set of carefully chosen constraints that make the modern web scalable. If we understand these constraints, we understand why backend systems are built the way they are.

0. Things to remember before DeepDive

Before we dive into HTTP’s design and constraints, it helps to align on a few foundational ideas.
These aren’t HTTP details they are the assumptions HTTP is built on.

Keeping these in mind will make the rest of the article much easier to reason about.

A. The Client–Server Model

HTTP is built on a strict client–server architecture.

This means:

  • The client always initiates communication

  • The server only responds

  • The server never calls the client directly

This constraint simplifies everything:

  • Servers don’t track client lifecycles

  • Load balancers can route freely

  • Failures remain isolated

Important Insight
HTTP is asymmetric by design.
All complexity starts at the client, not the server.

B. A Brief Note on TCP (What HTTP Relies On)

HTTP does not send bytes directly over the network.

It relies on TCP for transport.

TCP provides:

  • Reliable delivery (no silent packet loss)

  • Ordered data (bytes arrive in sequence)

  • Flow control and congestion handling

Because of TCP:

  • HTTP can assume messages arrive intact

  • HTTP does not worry about retransmissions

  • HTTP can focus purely on message semantics

💡 Mental Model
TCP handles how data moves.
HTTP defines what the data means.

(Modern HTTP evolves this, but the idea still holds.)

C. HTTP Versions and Why They Exist

HTTP versions exist because constraints changed, not because earlier versions were bad.

Each version solves a specific problem.

HTTP/1.0

  • One request per connection

  • Simple, but slow

  • Designed for early web usage

HTTP/1.1

  • Persistent connections (keep-alive)

  • Reduced connection overhead

  • Huge performance improvement

HTTP/2

  • Multiplexing multiple requests

  • Binary framing

  • Better performance under high concurrency

HTTP/3

  • Built on QUIC (over UDP)

  • Faster handshakes

  • Better performance on unstable networks

Important Insight
HTTP evolves to solve latency and reliability, not semantics.

1. The Original Problem: Machines at Scale Need Rules

Imagine millions of computers trying to talk to each other without a standard. Without a "rulebook," communication would be chaos. You would face four immediate problems:

  1. Initiative: Who talks first? Does the server push data, or does the client pull it?

  2. Delimitation: How do we know when a message ends and the next one begins?

  3. Context: How does the receiver know if they are receiving an image, a video, or a password?

  4. Agreement: How do we agree on what a "success" or a "failure" looks like across different programming languages?

To solve this, we need a standardized communication protocol. While we have many options today: WebSockets for real-time, gRPC for high-performance internal calls, or MQTT for IoT. HTTP remains the "English" of the internet.

HTTP exists to answer these coordination questions with the smallest possible rulebook.

2. HTTP is stateless. But WHY???

What is stateless and what it have a connection with HTTP? Most engineers will say :

“The server doesn’t store session data.”

That is technically correct, but it misses why this constraint exists and why it matters.

To understand statelessness, we need to look at what the alternative would be.

What If HTTP Were Stateful?

Imagine a server that remembers every client.

After your first request, the server keeps:

  • Who you are

  • What you asked for before

  • Where you are in a workflow

At first glance, this sounds convenient. Less data sent per request. Less repetition.

But now ask the uncomfortable questions:

  • What happens if that server crashes?

  • What if traffic spikes and we need 10 more servers?

  • How do we share memory between machines?

  • What happens when a load balancer routes you to a different server?

State becomes a liability.

Once the server remembers clients, it must:

  • Store that memory somewhere

  • Synchronize it across machines

  • Recover it after failures

This complexity grows faster than traffic.

The HTTP Decision: No Memory Between Requests

The HTTP Decision: No Memory Between Requests

HTTP takes a hard stance:

Every request must be treated as if it is the first time the server has ever seen the client.

This is what statelessness means.

  • No hidden memory

  • No implicit context

  • No assumptions about previous requests

If the server needs information, the client must send it every time.

Authentication, intent, metadata, all of it travels with the request.

Why Statelessness Enables Scale

This single constraint unlocks several powerful properties.

1. Horizontal Scaling Becomes Trivial

Any server can handle any request.

  • No session affinity

  • No sticky routing

  • No shared memory requirements

Add more servers → handle more traffic.

2. Failures Become Cheap

If a server dies:

  • No user state is lost

  • Another server can continue immediately

Stateless systems fail gracefully.

3. Load Balancers Become Simple

Load balancers don’t need to understand:

  • Users

  • Sessions

  • Workflows

They only forward requests.

This simplicity is not accidental it is designed.

“But HTTP Has Cookies, Tokens, Sessions…”

Yes and that’s the key insight.

Important
HTTP itself is stateless.
Applications built on top of HTTP reintroduce state explicitly.

Cookies, JWTs, and session IDs are:

  • Sent by the client

  • Included with every request

  • Read, not remembered, by the server

The state exists but outside the protocol, not inside it.

This preserves HTTP’s core constraint while still allowing real applications to exist.

A Useful Mental Model

Think of HTTP like a government office form.

Every time you visit:

  • You fill out the form again

  • You attach your ID again

  • You explain your request again

Inefficient for a single person.
Extremely scalable for millions.

Statelessness trades local convenience for global scalability.

Why This Matters for Backend Engineers

Once you understand statelessness, many backend design choices suddenly make sense:

  • Why auth tokens are sent on every request

  • Why APIs prefer idempotent operations

  • Why caches and CDNs work so well

  • Why microservices can be replicated freely

Statelessness is not a limitation.

It is the foundation that allows HTTP-based systems to scale to the size of the internet.

Next, the natural question becomes:

If the server remembers nothing, how does it understand what the client wants?

That leads us to the next section:
Requests, Responses, and the Shape of an HTTP Message.

3. Meaning in a Stateless World: Requests and Responses

If the server remembers nothing, a natural question arises:

How does the server understand what the client wants?

The answer is simple but powerful:

Everything the server needs to know must be inside the request.

HTTP solves this by defining a strict, predictable structure for communication.
Every interaction is broken into two parts:

  • A request from the client

  • A response from the server

No side effects.
No hidden context.

The HTTP Contract

At a high level, HTTP defines a contract:

  • The client sends a request message

  • The server replies with a response message

  • Both messages follow a known format

This predictability is what allows:

  • Browsers

  • Servers

  • Proxies

  • Load balancers

  • CDNs

…to all interoperate without knowing anything about each other’s internals.

The Shape of an HTTP Request

An HTTP request is not just raw data.
It has three conceptual layers, each with a clear responsibility.

METHOD PATH VERSION
Headers

Body

Let’s break this down.

1. Intent: Method + Path

The first line answers two critical questions:

  • What does the client want to do?

  • Which resource is it talking about?

Example:

PUT /api/users/123 HTTP/1.1
  • PUT → intent (replace a resource)

  • /api/users/123 → target

  • HTTP/1.1 → rules of interpretation

This line alone already carries meaning, even before reading any data.

2. Metadata: Headers

After intent comes context.

Headers are key–value pairs that describe:

  • Who is making the request

  • How the data is formatted

  • How the connection should behave

  • How the server should interpret the body

Example:

Content-Type: application/json
Authorization: Bearer <token>
User-Agent: Mozilla/5.0

Important Insight
Headers are processed before the body.

This allows:

  • Routing decisions

  • Authentication checks

  • Caching logic

  • Content negotiation

…without ever touching the payload.

Types of Headers (Mental Model)

Instead of memorizing headers, it helps to group them by purpose.

Request Headers

  • User-Agent – where the request is coming from

  • Authorization – Carries the credentials (like a JWT or API Key) to prove who you are.

  • Cookie – Sends back small pieces of data previously stored by the server(client-side state)

  • Accept –Tells the server what format the client understands (e.g., application/json or text/html). This is the foundation of Content Negotiation.

General Headers

  • Date - The timestamp of when the message was generated.

  • Cache-Control -The "instruction manual" for browsers and CDNs on how long they can keep a copy of the response before asking the server again.

  • Connection - Tells the system whether to close the network "pipe" after the request or keep it open (keep-alive) for more messages.

Representation Headers

  • Content-Type - The MIME type of the body (e.g., application/json, image/png). Without this, the receiver just sees a wall of binary 1s and 0s.

  • Content-Length - The exact size of the body in bytes. This is how the receiver knows when the message has officially ended.

  • Content-Encoding - Tells the receiver if the data is compressed (e.g., gzip or br).

Security Headers

  • These headers protect the user by telling the browser to restrict certain behaviors.

    • Strict-Transport-Security (HSTS): Tells the browser: "Never talk to me over plain HTTP again; use HTTPS only."

    • Content-Security-Policy (CSP): A powerful tool that tells the browser which scripts, images, and plugins are allowed to load. It prevents Cross-Site Scripting (XSS).

    • X-Frame-Options: Prevents your site from being put in an <iframe> on another site, stopping "Clickjacking" attacks.

    • X-Content-Type-Options: Set to nosniff, it stops the browser from "guessing" the file type, which prevents hackers from disguising a script as an image.

    • Set-Cookie: Sent by the server to tell the browser: "Store this data and send it back to me in every future request's Cookie header."

Note, we can also define custom headers for application-specific needs.

3. Data: The Body

The body contains the actual data being sent.

Example:

{
  "firstname": "John"
}

Not all requests have a body:

  • GET usually doesn’t

  • POST and PUT often do

The body is optional, but when present, it is always separated by a blank line.

That blank line is not cosmetic.
It is the boundary between control information and payload.

Why Headers Are Not in the Body

A common beginner question is:

Why not put everything in the body?

Because headers exist for speed, safety, and intermediaries.

Headers can be:

  • Read without parsing large payloads

  • Inspected by proxies and caches

  • Used to make early decisions

Headers are the label on a package.
The body is what’s inside the box.

Delivery systems must read the label quickly not open every box.

The Shape of an HTTP Response

Responses follow the same philosophy.

VERSION STATUS_CODE STATUS_TEXT
Headers

Body

Example:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache

{ "id": 123 }

Again:

  • Status line → outcome

  • Headers → metadata

  • Body → payload

The symmetry is intentional.

Why This Structure Scales

This rigid structure enables:

  • Streaming

  • Partial reads

  • Caching

  • Compression

  • Protocol upgrades

Most importantly, it enables intermediaries.

Load balancers, gateways, and CDNs don’t need to understand your application they only need to understand HTTP.

That is a massive architectural win.

4. HTTP as Extensibility and Remote Control

So far, we’ve seen that HTTP is:

  • Stateless

  • Structured

  • Explicit

But these properties alone don’t explain why HTTP became the protocol for backend systems.

The deeper reason is this:

HTTP turns the network into a remote control surface.

Remote Control, Not Just Data Transfer

When a client sends an HTTP request, it is not just sending data.
It is instructing a remote system to do something.

  • Fetch a resource

  • Create something new

  • Update existing state

  • Delete something

HTTP turns distributed systems into controllable systems.

The server exposes capabilities.
The client invokes them using standardized messages.

This is why HTTP works so well for:

  • APIs

  • Microservices

  • Service-to-service communication

  • Browser ↔ backend interactions

Extensibility Without Breaking the World

Another key design decision:

HTTP is extensible by design

It allows new behavior to be added without changing the core protocol.

Examples:

  • New headers can be introduced

  • New methods can be defined

  • New status codes can be added

  • New security rules can be layered on top

Old clients keep working.
New clients get new capabilities.

This property is why HTTP has survived decades of change.

5. HTTP Methods: Expressing Intent

In a stateless system, intent must be explicit.

HTTP methods exist for exactly this reason.

They answer a simple question:

What does the client want the server to do?

Methods are not about implementation.
They are about semantics.

Common HTTP Methods (High-Level)

  • GET – retrieve data

  • POST – cause a change (usually create)

  • PUT – replace a resource

  • PATCH – partially update a resource

  • DELETE – remove a resource

  • OPTIONS – ask what is allowed

The same URL can behave very differently depending on the method.
That difference is intentional.

6. Idempotency: Safety at Scale

Once systems become distributed, requests can:

  • Fail midway

  • Be retried

  • Be duplicated

HTTP addresses this with idempotency.

What Idempotent Means

An operation is idempotent if:

Making the same request multiple times produces the same result.

Idempotent Methods

  • GET

  • PUT

  • DELETE

  • OPTIONS

These are safe to retry.

If a network failure happens, the client can resend the request without fear.

Non-Idempotent Methods

  • POST

Calling POST multiple times may create:

  • Duplicate records

  • Multiple side effects

This distinction is critical for:

  • Load balancers

  • Retries

  • Distributed systems

7. OPTIONS: Discovering Capabilities

In a system built around intent, sometimes the client needs to ask:

“What am I allowed to do here?”

That is the role of the OPTIONS method.

OPTIONS allows a client to:

  • Discover supported methods

  • Understand server constraints

  • Safely interact without guessing

It does not perform an action.
It asks questions.

8. CORS: A Browser-Enforced Constraint

CORS (Cross-Origin Resource Sharing) is often misunderstood.

Important Insight
CORS is not a server security feature.
It is a browser-enforced rule.

Browsers restrict:

  • Which origins can call which APIs

  • Which headers and methods are allowed

Servers simply declare permissions.
Browsers enforce them.

The CORS Preflight Flow (High-Level)

For certain requests, the browser performs a preflight check.

The flow looks like this:

  1. Browser sends an OPTIONS request

  2. Server responds with allowed methods, headers, and origins

  3. Browser evaluates the response

  4. If allowed → actual request is sent

  5. If not → request is blocked by the browser

The backend may still work the browser just refuses to expose it.

Why CORS Exists

Without CORS:

  • Any website could call any API

  • Users’ credentials could be abused

CORS protects users, not servers.

The Deeper Insight

HTTP combines:

  • Statelessness

  • Explicit intent

  • Extensibility

  • Safety mechanisms

This allows it to act as:

  • A communication protocol

  • A control interface

  • A compatibility layer between decades of systems

And all of this works because HTTP chooses constraints over convenience.

9. HTTP Status Codes and Meaningful Responses

If HTTP methods express intent, then status codes express outcome.

Once a server processes a request, it must answer a simple question:

What happened?

HTTP status codes exist to communicate that answer clearly, compactly, and consistently.

They are not decorative numbers.
They are control signals.

Why Status Codes Exist at All

Imagine if every response just returned data.

How would a client know:

  • Whether a request succeeded?

  • Whether it should retry?

  • Whether the error was its fault or the server’s?

  • Whether the resource moved?

Without status codes:

  • Clients would guess

  • Retries would be unsafe

  • Monitoring would be unreliable

  • Distributed systems would break down

Status codes solve this by encoding meaning into a small, machine-readable signal.

The Contract: Meaning Before Payload

An HTTP response communicates meaning in layers:

HTTP/1.1 200 OK
Headers

Body

The status line comes first.

This is intentional.

Clients, proxies, and load balancers can:

  • Read the status code

  • Make decisions

  • Without ever parsing the body

Important Insight
The status code is often more important than the response body.

Status Code Categories (The Mental Model)

Instead of memorizing individual codes, HTTP groups them by intent.

1xx — Informational

  • The request was received

  • Processing is continuing

Rarely used in application-level APIs.

2xx — Success

The request was understood and handled successfully.

Common examples:

  • 200 OK – successful request

  • 201 Created – new resource created

  • 204 No Content – success, but no body

Use different 2xx codes to express what kind of success occurred.

3xx — Redirection

The request is valid, but the client must:

  • Look elsewhere

  • Repeat the request at a different location

Examples:

  • 301 Moved Permanently

  • 302 Found

  • 304 Not Modified (critical for caching)

Redirects are about control flow, not failure.

4xx — Client Errors

The server is saying:

“I received your request, but there is something wrong with it.”

Common examples:

  • 400 Bad Request – malformed input

  • 401 Unauthorized – missing or invalid authentication

  • 403 Forbidden – authenticated, but not allowed

  • 404 Not Found – resource does not exist

  • 409 Conflict – state conflict

  • 422 Unprocessable Entity – validation failed

Important Insight
4xx errors mean the client should change the request, not retry it blindly.

5xx — Server Errors

The server is saying:

“Your request was valid, but I failed to process it.”

Examples:

  • 500 Internal Server Error

  • 502 Bad Gateway

  • 503 Service Unavailable

  • 504 Gateway Timeout

These indicate:

  • Crashes

  • Timeouts

  • Dependency failures

5xx errors are often retryable, but not always.

Status Codes as Control Signals

In real systems, status codes drive behavior:

  • Load balancers decide retries

  • Clients decide whether to show errors

  • Monitoring systems trigger alerts

  • Caches decide whether to store responses

All of this happens before reading the body.

That’s why status codes must be:

  • Accurate

  • Intentional

  • Consistent

Meaningful Responses Go Beyond Numbers

A good HTTP response combines:

  • A correct status code

  • Clear headers

  • A useful body (when needed)

Example:

HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": "User already exists"
}

The status code tells what category of outcome occurred.
The body explains why.

Both matter, but they serve different purposes.

Common Mistakes Backend Engineers Make

  • Returning 200 OK for every response

  • Encoding error meaning only in the body

  • Using 500 for client mistakes

  • Treating status codes as optional

Important Insight
If everything returns 200, HTTP loses its value.

What Comes Next

Now that we understand:

  • Statelessness

  • Message structure

  • Intent (methods)

  • Outcomes (status codes)

The final missing piece is performance:

How does HTTP scale to billions of requests efficiently?

That leads us to:
Caching, Content negociation, persistent connection and keep alove, multipart data, stream data, Performance, and Why HTTP Is Fast Enough, sszl https, tls,

10. Performance at Scale: Why HTTP Is Fast Enough

At this point, HTTP might seem inefficient.

  • Stateless

  • Repetitive

  • Text-based

  • Verbose

So a reasonable question is:

How does something this simple handle billions of requests per day?

The answer is not one feature: it is a set of performance-oriented constraints layered on top of HTTP.

11. Caching: Avoiding Work Entirely

The fastest request is the one you never send to the server.

HTTP is designed to make caching a first-class concept.

How HTTP Enables Caching

Caching decisions are driven by headers, not application logic.

Common cache-related headers:

  • Cache-Control

  • ETag

  • If-None-Match

  • Expires

These allow:

  • Browsers to reuse responses

  • CDNs to serve data without hitting origin servers

  • Servers to avoid recomputation

Example flow:

  1. Client requests a resource

  2. Server returns response with cache metadata

  3. Client reuses cached data until it expires

  4. Server is never involved

Important Insight
Caching is not an optimization it is a core HTTP capability.

12. Content Negotiation: One Endpoint, Many Representations

Different clients want different things.

  • Browsers

  • Mobile apps

  • CLI tools

  • Different locales

  • Different compression formats

HTTP solves this using content negotiation.

Clients express preferences using headers:

  • Accept

  • Accept-Encoding

  • Accept-Language

Servers respond with the best match.

Example:

  • Client prefers application/json

  • Accepts gzip

  • Wants English content

The server adapts without changing the URL.

💡 Insight
Content negotiation allows flexibility without fragmentation.

13. Persistent Connections and Keep-Alive

Opening a TCP connection is expensive.

Early HTTP versions opened a new connection for every request slow and wasteful.

The Solution: Keep-Alive

Modern HTTP keeps connections open:

  • Multiple requests

  • Same connection

  • Reduced handshake cost

This dramatically improves:

  • Latency

  • Throughput

  • Server efficiency

This is why HTTP/1.1+ feels fast even though it’s text-based.

14. Multipart Data: Sending More Than One Thing

Sometimes, a request needs to send:

  • Files

  • Metadata

  • Mixed content

HTTP supports this via multipart requests.

Used heavily for:

  • File uploads

  • Form submissions

  • Media transfers

Multipart allows:

  • Clear boundaries between parts

  • Streaming large files

  • Partial processing

All without inventing a new protocol.

15. Streaming Data: Not Everything Needs to Finish

HTTP does not require responses to be fully buffered.

It supports streaming:

  • Chunked transfer encoding

  • Progressive responses

  • Large downloads

  • Video and audio streams

This allows:

  • Faster time-to-first-byte

  • Lower memory usage

  • Real-time data delivery

Important Insight
HTTP is not request–wait–response only.
It can be incremental and continuous.

16. Why HTTP Is “Fast Enough”

HTTP wins not by being the fastest protocol ever invented, but by being:

  • Cache-friendly

  • Proxy-friendly

  • Retry-friendly

  • Tooling-friendly

  • Infrastructure-friendly

Its performance comes from:

  • Avoiding work

  • Reusing connections

  • Letting intermediaries help

Insight
HTTP scales by delegation, not raw speed.

17. HTTPS, SSL, and TLS: Trust Was Missing

Original HTTP assumed a friendly network.

Reality proved otherwise.

Anyone on the network could:

  • Read traffic

  • Modify responses

  • Impersonate servers

HTTPS Fixes This

HTTPS is simply:

HTTP + TLS

TLS provides:

  • Encryption – no one can read the data

  • Authentication – you know who you’re talking to

  • Integrity – data cannot be altered silently

Note SSL is deprecated.
Modern systems use TLS.

The Cost of Security (And Why It’s Worth It)

TLS adds:

  • Handshakes

  • Cryptography

  • Slight overhead

But modern optimizations (session reuse, hardware acceleration) make this cost negligible.

Today’s reality:

If it’s not HTTPS, it’s broken.

Final Insight: Why HTTP Endures

HTTP survives because it is:

  • Simple at its core

  • Extensible at the edges

  • Strict where it matters

  • Flexible where it helps

It does not try to do everything.
It defines rules, then lets the ecosystem innovate.

That is why:

  • Browsers

  • Backends

  • CDNs

  • Load balancers

  • Security layers

…can all evolve independently and still work together.

Final Takeaway

HTTP is not impressive because it is clever.

It is impressive because it is disciplined.

By understanding its constraints, you understand:

  • Why backend systems scale

  • Why APIs look the way they do

  • Why the web still works

And that is the real art behind HTTP.

13 views

Building Backend Systems from Zero

Part 3 of 3

A backend engineering series exploring systems from first principles starting with why problems exist before how they’re solved. As I learn, I document my journey through APIs, databases, auth, scalability, and distributed systems.

Start from the beginning

Backend First Principles: The Art of Routing

Welcome back to the Backend First Principles series! Today, we’re stripping away the fancy frameworks (Express, FastAPI) to look at the skeletal structure of how the web actually works. At its core, every backend developer is a Digital Postmaster. Wh...