Envoy Gateway Core Concepts: Gateway, Listener, Proxy, and the Route Family Explained
A lot of people's first impression of Gateway API is something like: "The term count isn't that high, but my brain feels like it's watching a cast list full of characters with similar names — I can't tell who's the protagonist and who's a side character." This post is here to cut through that confusion, and cover the common route types along the way.
The Overall Architecture
The official Envoy Gateway concepts break the system into three layers:
- User Configuration: The
Gateway APIresources and Envoy Gateway extension CRDs you write - Envoy Gateway Controller: Reads resources, validates them, and translates config
- Envoy Proxy: The data plane that actually handles traffic
This means what you're usually editing is not Envoy Proxy itself — you're "declaring what you want." Envoy Gateway translates those declarations into config that Envoy Proxy can execute. That's what makes it nicer than writing proxy config by hand.
The Key Roles
Just remember these for now:
GatewayClass: Defines "which Gateway implementation to use in this cluster"Gateway: Defines "where the ingress is and what protocol it speaks"Listener: Defines a specific port/protocol/hostname ingress slotRoute: Defines "which requests go to which Service"Envoy Proxy: The actual Gateway Proxy that receives and forwards traffic
In plain English:
GatewayClassis the spec sheetGatewayis the building's front entranceListeneris the front deskRouteis the signage inside the buildingEnvoy Proxyis the security system doing access control and escorting
Without any one of these, traffic won't get where you want it to go.
A Minimal YAML That Shows the Full Picture
Here's the smallest understandable example:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: backend
spec:
parentRefs:
- name: eg
hostnames:
- "www.example.com"
rules:
- backendRefs:
- name: backend
port: 3000Chained together, the logic is:
GatewayClasssays theEnvoy Gatewaycontroller is in chargeGatewaydeclares one HTTP ingress on port80HTTPRoutesays requests forwww.example.comshould go tobackend:3000Envoy Gatewaytranslates all of this forEnvoy Proxy
Understanding Each Field
GatewayClass
This is a cluster-level ingress type definition. The most critical field is usually:
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controllerThis simply means:
"This GatewayClass is managed by the Envoy Gateway controller."
If the controllerName doesn't match, it's like ordering delivery to the wrong company — nobody picks it up.
Gateway
This defines "what the ingress looks like." The most-referenced field is listeners:
listeners:
- name: http
protocol: HTTP
port: 80This means:
- Open a listener named
http - Accept HTTP traffic
- Listen externally on port
80
For HTTPS, you'd typically add another listener with protocol: HTTPS and attach TLS config.
Gateway commonly manages:
- External port and protocol
- Per-listener hostname
- TLS termination location
- Which namespaces' routes can attach
Gateway is more of a platform-layer concern — its ownership typically sits with the platform team.
Listener
This is the most commonly overlooked role for beginners, but it's actually crucial.
A listener is an outward-facing ingress slot on the Gateway. It defines:
nameportprotocolhostnametlsallowedRoutes
Example:
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: api.example.comThis means:
- This slot is named
https - Accepts HTTPS
- Listens on port
443 - Dedicated to
api.example.com
If you have multiple listeners like:
httpfor port 80httpsfor port 443grpcfor port 50051
You're opening multiple ingress slots on the same Gateway, each capable of attaching different routes.
Envoy Proxy
Many people focus only on the YAML and forget that Envoy Proxy is what actually handles live traffic.
Its role is:
- Receiving client requests
- Matching against config pushed by Envoy Gateway
- Forwarding traffic to the appropriate backend
- Handling TLS, headers, timeouts, retries, and other data-plane behaviors
So think of Envoy Gateway as the "control plane," and Envoy Proxy as the "data plane / Gateway Proxy."
The Route Family
Route isn't just HTTPRoute. The whole family is central to Gateway API's design.
HTTPRoute
This is what you'll write and modify most often. Three key fields:
spec:
parentRefs:
- name: eg
hostnames:
- "www.example.com"
rules:
- backendRefs:
- name: backend
port: 3000parentRefs: Which Gateway to attach tohostnames: Which Host header triggers this rulebackendRefs: Where to send matched requests
The most common confusion: Gateway is not where you write fine-grained routing — HTTPRoute is what actually decides "how to split traffic."
GRPCRoute
If you're handling gRPC, GRPCRoute is more natural than forcing it into HTTPRoute.
It can match on:
- gRPC hostname
- gRPC service
- gRPC method
- headers
Example:
matches:
- method:
service: com.example.User
method: LoginThis semantics aligns naturally with gRPC — you're not just matching URL paths, you're matching directly against the gRPC service/method model.
The official docs also note: if GRPCRoute and HTTPRoute share the same listener and have conflicting hostnames, implementations should reject one. Basically, don't let HTTP and gRPC fight over the same hostname.
TCPRoute
TCPRoute handles raw TCP traffic.
Unlike HTTPRoute, it doesn't understand path or header semantics at L7 — it's closer to L4 forwarding.
Appropriate scenarios:
- Non-HTTP protocol services
- Pure TCP services
- Routing connections to different backends based only on listener port
Databases with custom protocols or proprietary TCP protocols are typical TCPRoute use cases.
TLSRoute
TLSRoute handles TLS traffic and is particularly common in TLS passthrough scenarios.
Core concept:
- The Gateway doesn't necessarily terminate TLS
- It may route traffic based solely on the SNI hostname in the TLS handshake
- Encrypted traffic is preserved all the way to the backend
This matters for scenarios requiring end-to-end encryption, or where you don't want TLS terminated at the Gateway.
How to Choose a Route Type
| Requirement | Use This |
|---|---|
| Websites, REST APIs, general web traffic | HTTPRoute |
| gRPC service/method routing | GRPCRoute |
| Raw TCP traffic | TCPRoute |
| TLS passthrough / SNI-based routing | TLSRoute |
This table matters because many people instinctively write HTTPRoute for everything. But if you're actually dealing with gRPC or TCP, forcing it into HTTPRoute just makes the YAML increasingly awkward.
Why Routes Are Easier to Reason About Than Ingress
Old Ingress configs often squeezed too many responsibilities into a single resource, leading to some persistent pain points:
- Platform config and app routing mixed together
- Advanced features expressed via annotations with poor readability
- Limited expressiveness for non-HTTP protocols
Gateway API's approach is to split responsibilities:
- Platform teams manage
GatewayClass/Gateway - App teams manage their own
HTTPRoute
This separation works well for multi-person collaboration. You don't need to touch the entire ingress layer just to change a path — team stepping-on-each-other rates drop significantly.
Start Paying Attention to Status
Beyond spec, gradually build the habit of checking status. Especially for HTTPRoute and Gateway:
kubectl get gateway eg -o yaml
kubectl get httproute backend -o yamlStart by checking:
- Whether the route was
Accepted - Whether the gateway listener is Ready
- Whether an address was successfully assigned
It's like checking exam results. Don't just verify that you submitted — verify that it was graded and passed.
One-Line Summary
Think of GatewayClass, Gateway, Listener, Route, and Envoy Proxy as "who manages it, how the ingress opens, how each slot connects, how traffic splits, and who executes it" — and you've already grasped 80% of the core concepts.
💡 Beginners often dive straight into CRD details. Don't rush — get these roles straight first, and the YAML will stop feeling like meeting strangers every time.
Next Step
Now that concepts are in place, the next post digs into the most common HTTP routing scenarios — host, path, header, and traffic splitting: 👉 HTTP Routing in Practice