After 28 Years, HTTP Still Can’t Agree on What ‘Upstream’ Means

You’ve probably configured a proxy at some point in your career. You set an upstream server, pointed your traffic at it, and everything worked. Simple, right?

Except the person who wrote that proxy configuration might have a completely different mental model of what upstream means than you do. And neither of you is wrong.

That’s not a bug. That’s not a misconfiguration. That’s the state of HTTP in 2025 — nearly three decades after the protocol was defined, and we still can’t agree on whether upstream means toward the client or toward the server.

This came to light again recently in an IETF HTTP Working Group discussion about incremental HTTP messages. A contributor submitted a comment that stopped everyone cold: after 28 years, the definitions of upstream and downstream are still heavily contested. Not in some academic, theoretical sense — in the actual, shipping code that runs the internet.

The internet runs on a protocol where the most basic directional terms mean different things to different people, and nobody has the authority to fix it.

Here’s the core problem. HTTP uses a request/response model that looks linear on paper: client sends request, server sends response. But in the real world, that line is crowded with intermediaries — proxies, gateways, load balancers, CDNs, service meshes. Each one sits in the middle and has to decide: when I forward a request, am I going upstream or downstream?

The answer depends entirely on where you’re standing.

If you’re a client, the server is upstream — that’s where your requests go. If you’re a server, the client is upstream — that’s where requests come from. If you’re a proxy in the middle, both directions are upstream depending on which side you’re looking at. The terms are perspective-dependent, and no amount of specification writing can fix that without picking a perspective and alienating everyone who picked the other one.

Take Envoy proxy, one of the most widely deployed service proxies in the world. Envoy calls the backend servers upstream clusters. To Envoy, forwarding a request means going upstream. This makes perfect sense if you think of Envoy as a client making requests to backends. But if you think of the data flowing from the original client through Envoy to the server, then Envoy is forwarding downstream. Same traffic. Opposite labels.

When someone in the working group pointed this out, the response was blunt: Fix the Envoy proxy terminology so that it isn’t obviously wrong.

But here’s the thing — it’s not obviously wrong. It’s obviously ambiguous. There’s a difference.

When two smart people look at the same word and both think the other is obviously wrong, the problem isn’t the people. The problem is the word.

This isn’t just semantics. It’s the kind of ambiguity that silently breaks systems. You inherit a codebase where someone named a variable upstream_connection. You assume it means the connection to the backend. The original author meant the connection from the client. You wire your logic accordingly. Everything compiles. Tests pass. Then at 3 AM on a Saturday, traffic starts routing through the wrong path because your mental model didn’t match the person who wrote the config three years ago.

We like to think of HTTP as a solved problem. The spec is decades old. Every language has mature libraries. Every framework handles it. But underneath that stability is a layer of conceptual ambiguity that we’ve all been papering over with context and convention.

The working group is now grappling with whether to even attempt a fix. The tension is real: standardize the terminology and you break every implementation that embedded the other interpretation. Leave it ambiguous and you guarantee that the next generation of engineers will rediscover this same confusion, file the same bugs, and have the same arguments.

Twenty-eight years. The web has gone from static pages to streaming AI responses. We’ve reinvented the browser, the server, the network, and the application model multiple times over. And through all of it, we never resolved whether upstream means toward the client or toward the server.

Maybe the real lesson isn’t that HTTP is broken. Maybe it’s that the most important infrastructure in the world doesn’t need to be perfectly defined — it just needs to be useful enough that nobody can afford to stop using it long enough to fix it.

That’s not a comforting thought. But it’s probably the truest thing you’ll read about network protocols today.

FAQ

Q: Can't the IETF just pick one definition and update the spec?

A: They could, but it wouldn't matter. The spec isn't the problem — existing implementations are. Envoy, nginx, and dozens of other tools have baked their interpretation into APIs, config files, and documentation. Changing the spec would make the documentation correct and the running code wrong, which is arguably worse.

Q: How does this actually cause bugs in practice?

A: When you inherit a codebase or config, you assume upstream means what you think it means. If the original author had the opposite mental model, your assumptions silently diverge. Everything works until a specific traffic pattern exposes the mismatch — usually in production at the worst possible time.

Q: Isn't this just bikeshedding by a standards committee?

A: No. The fact that this ambiguity has persisted for 28 years across the most important protocol on earth reveals something deeper: infrastructure doesn't need to be perfectly specified to be universally adopted. It needs to be useful enough that fixing it costs more than living with it.

📎 Source: View Source