What are upstream and downstream concepts in Envoy Proxy?
Quick Answer
In Envoy terminology, downstream refers to the client that connects to Envoy (sends requests), and upstream refers to the backend service that Envoy forwards requests to. Envoy sits between downstream clients and upstream services, processing traffic in both directions through its filter chain.
Detailed Answer
Think of Envoy as a river dam. Downstream is the direction water flows toward, meaning the clients that receive responses. Upstream is where the water comes from, meaning the backend services that generate the responses. Envoy sits in the middle, controlling the flow of water in both directions. This terminology is consistent throughout Envoy's documentation, configuration, and statistics.
In Envoy's architecture, a downstream connection is established when a client connects to one of Envoy's listeners. This client could be an end user's browser, another microservice, or any application making a network request. The downstream side is where Envoy accepts connections and receives requests. An upstream connection is what Envoy creates when it needs to forward a request to a backend service. The upstream side is where Envoy acts as a client, connecting to the endpoints defined in its cluster configuration. This bidirectional terminology is fundamental because Envoy processes traffic differently in each direction and tracks separate statistics for downstream and upstream activity.
The distinction becomes critical when reading Envoy statistics and logs. Downstream metrics include counters like downstream_cx_total (total downstream connections), downstream_rq_total (total downstream requests), and downstream_cx_active (currently active downstream connections). These tell you about the load Envoy is receiving from clients. Upstream metrics include upstream_cx_total, upstream_rq_total, upstream_rq_timeout, and upstream_rq_retry, which tell you about Envoy's communication with backend services. When debugging a 503 error, understanding this distinction is essential: a downstream 503 means Envoy sent a 503 to the client, but the root cause might be an upstream connection failure, an upstream timeout, or a circuit breaker trip on the upstream cluster.
In a service mesh with sidecar proxies, the upstream and downstream terminology applies at each hop. When the payments-api calls the order-service, the request passes through two Envoy proxies. The payments-api's Envoy sidecar treats the payments-api container as the downstream client and the order-service as the upstream. The order-service's Envoy sidecar treats the payments-api's Envoy as the downstream client and the order-service container as the upstream. Understanding this double-proxy hop is essential for interpreting metrics and access logs correctly in a service mesh environment.
A common source of confusion is that the upstream/downstream terminology in Envoy is opposite to how some people intuitively think about data flow. People sometimes assume upstream means the client because it is 'higher up' in the call chain. In networking and proxy terminology, upstream always refers to the server or backend that provides the content, and downstream always refers to the client or consumer that requests the content. This convention is consistent across Envoy, Nginx, HAProxy, and most proxy technologies. Getting this terminology right is essential for clear communication in incident response scenarios.