Gateway API v1.6.0 shipped on June 29, 2026, and the headline is simple: UDPRoute is General Availability, promoted out of the v1alpha2 experimental channel alongside TCPRoute and TLSRoute. For a self-hosted PaaS, that reads like good news — DNS, QUIC, game servers, and custom protocols finally get a stable, typed CRD instead of an experimental one that could change shape under you. But "GA in the spec" and "works on your cluster today" are two different claims, and the gap between them is where this actually gets interesting.
Here's the short version, before the detail: whether UDPRoute helps you this week depends entirely on which Gateway API implementation you run, there's a real upgrade-order trap that will drop traffic if you get it wrong, and even once it works, UDPRoute doesn't solve multi-tenant routing the way HTTPRoute does — it creates a new capacity-planning problem instead. We'll walk through all three with a working example.
What Actually Graduated in v1.6
Gateway API versions its resources independently — a CRD can be GA while a sibling CRD in the same API group is still experimental. As of v1.6.0, the following are GA under the gateway.networking.k8s.io/v1 API group:
| Resource | Status as of v1.6.0 |
|---|---|
| GatewayClass, Gateway, HTTPRoute, GRPCRoute | GA (unchanged, already stable) |
| TLSRoute | GA |
| TCPRoute | GA (new in v1.6) |
| UDPRoute | GA (new in v1.6) |
| ListenerSet, BackendTLSPolicy, ReferenceGrant | GA |
The practical change for TCPRoute and UDPRoute is that their stored apiVersion moves from gateway.networking.k8s.io/v1alpha2 to gateway.networking.k8s.io/v1, and the v1alpha2 versions of both are now marked for future removal. The release also lands GEP-2645: a formal conformance test suite for UDPRoute, plus a new GATEWAY-UDP conformance profile. That last part matters more than it sounds — before v1.6, "UDPRoute support" was whatever each controller vendor decided to implement against a moving experimental spec. Now there's a pass/fail suite every implementation is measured against the same way, which is the actual substance behind "GA": not just a version bump, but a shared, testable definition of correct behavior.
None of that changes what UDPRoute does. It routes raw UDP traffic — DNS, QUIC, game server protocols, VoIP, custom binary protocols — through the same GatewayClass/Gateway resource model that's probably already handling your fleet's HTTP ingress. What it changes is whether you can build on it without the ground shifting under you.
The Controller Reality Check
Gateway API is a spec; whether UDPRoute does anything depends on the controller behind your GatewayClass. As of mid-2026, support is uneven enough that "is UDPRoute GA" is the wrong question — the right one is "does my Gateway implementation ship it, and on what version":
| Implementation | UDPRoute status | The catch |
|---|---|---|
| Envoy Gateway (v1.7) | Full support, reconciles via gateway.networking.k8s.io/v1 | Must upgrade Gateway API CRDs to v1.6 and migrate existing route manifests to apiVersion: v1 before upgrading the controller — see below |
| Cilium | Not yet reconciled into the dataplane | TCPRoute/UDPRoute support is an open feature request (tracked in a public GitHub issue) as of April 2026; the CRDs can exist in-cluster without the dataplane acting on them |
| Traefik | Supports TCPRoute/UDPRoute from its experimental channel | Traefik's own Gateway API spec support is pinned to v1.5.1 — a minor version behind v1.6, so don't assume parity with the latest conformance profile |
The Envoy Gateway case is the one that will actually bite a fleet that's already on Gateway API (which, per this blog's own migration coverage, is where a PaaS routing tenant HTTPRoutes off Ingress-NGINX should already be). Envoy Gateway v1.7 requires the Gateway API CRDs to be at v1.6 first. If you have any existing TCPRoute or UDPRoute objects — even ones nobody's touched since they were created against the experimental channel — you have to convert their apiVersion to v1 before you bump the CRDs. Skip that step, or do it out of order, and those routes stop being served. Not a warning in the logs: dropped traffic, silently, on whatever was behind that route. The fix is procedural, not technical — audit existing TCPRoute/UDPRoute manifests for their apiVersion field, bump those first, then upgrade CRDs, then upgrade the controller — but it's exactly the kind of order-dependent step that's invisible until you're mid-upgrade with a page open.
A Worked Example: Adding UDPRoute Next to Existing HTTPRoutes
Say your fleet already migrated tenant ingress from Ingress-NGINX to Envoy-Gateway-backed HTTPRoute — the same Gateway object is terminating TLS on :443 for every tenant's HTTP traffic. A tenant now wants to run a stateless UDP workload: a CoreDNS instance answering on port 53, or a game server speaking a custom UDP protocol on a high port. Here's what gets added, not replaced.
First, the Gateway needs a UDP listener alongside its existing HTTPS one:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tenant-gateway
namespace: gateway-infra
spec:
gatewayClassName: envoy-gateway
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs: [{ name: tenant-wildcard-tls }]
- name: dns-udp
protocol: UDP
port: 5300
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels: { tenant: acme-corp }Then the UDPRoute itself, in the tenant's namespace, pointing at that listener by name:
apiVersion: gateway.networking.k8s.io/v1
kind: UDPRoute
metadata:
name: acme-coredns
namespace: tenant-acme-corp
labels: { tenant: acme-corp }
spec:
parentRefs:
- name: tenant-gateway
namespace: gateway-infra
sectionName: dns-udp
rules:
- backendRefs:
- name: acme-coredns-svc
port: 53That's the entire mechanism: no annotations, no separate Service of type LoadBalancer per tenant, no hand-rolled iptables/NodePort plumbing. Traffic hitting the Gateway's node on port 5300 gets forwarded to acme-coredns-svc:53 in the tenant's namespace, governed by the same ReferenceGrant-based cross-namespace access control already protecting HTTPRoute. A game server backend works identically — swap the listener port and backendRef for whatever port the game protocol uses. This is the "custom protocol" case the v1.6 release is aimed at: anything that speaks raw UDP now gets first-class routing instead of a bespoke workaround.
The Catch UDPRoute Doesn't Solve: One Port Per Tenant
Here's the part that's easy to miss if you're used to how HTTPRoute scales on a multi-tenant Gateway. HTTPRoute and TLSRoute both have a hostnames field — HTTPRoute matches on the Host header, TLSRoute matches on the SNI value from the TLS handshake. That's what lets dozens of tenants share one :443 listener on one IP: the Gateway reads a hostname out of the request itself and routes accordingly, before any backend sees the traffic.
UDPRoute has no hostnames field. Raw UDP has no equivalent of a Host header or SNI extension for the Gateway to inspect before delivery — a UDP packet is just a payload with no routing-relevant metadata the spec defines. Matching is entirely by which listener — meaning which port — the traffic arrived on. That's why the example above needed a dedicated dns-udp listener on port 5300 rather than reusing :443. If a second tenant wants their own UDP DNS instance, they need their own port (or their own Gateway IP), full stop. There's no way to multiplex two tenants' UDP services behind one shared port the way HTTPRoute multiplexes tenants behind one shared :443.
This is worth naming explicitly for QUIC, since it's the workload most people assume "UDP routing" was built for. HTTP/3 and QUIC-based protocols run over UDP, and it's tempting to read UDPRoute GA as "now I can Gateway-route QUIC traffic the way I route HTTPS." You can carry QUIC packets through a UDPRoute listener, but you get none of TLSRoute's SNI-based multiplexing on the way — QUIC's server-name information lives inside the encrypted handshake, and UDPRoute's matching stops at "which port did this arrive on." Routing multiple tenants' HTTP/3 backends by hostname still means terminating at the HTTPRoute/HTTPS layer (where a QUIC-aware implementation exposes it) rather than passing raw UDP through — UDPRoute alone gets you a transport for QUIC traffic, not tenant-aware QUIC routing.
For a Cluster-API-managed fleet, that turns "add UDP support" into a capacity-planning problem, not just a routing one: every tenant UDP service is now a line item against a finite pool of ports (or a finite pool of Gateway-fronting IPs, if you'd rather hand out IPs than manage a port registry). A platform that's been used to HTTPRoute's near-unlimited tenant density on a single IP needs an actual allocation scheme — a reserved port range per tenant, or per-tenant Gateways with their own IP — before UDPRoute-based services go from "the one pilot customer who asked for it" to "a general-availability feature every tenant can self-serve."
What to Actually Do With This
If your fleet is already on Gateway API for HTTP ingress — which, if you followed this blog's Ingress-NGINX retirement coverage, it should be by now — UDPRoute GA is the reason to finish standardizing on the full route-type family rather than bolting on a one-off NodePort hack the next time a tenant asks for a UDP-based service. The concrete steps, in order:
- Confirm your
GatewayClassimplementation actually ships UDPRoute dataplane support, not just the CRD. Check the version, not just the vendor name — Cilium and older Traefik builds will accept a UDPRoute object without doing anything with it. - Audit for any existing TCPRoute/UDPRoute manifests before touching CRD versions. If they're still
v1alpha2, convert them tov1first — do this before the CRD upgrade, not after, or those routes go dark. - Design a port/IP allocation scheme before the first UDP tenant, not after the third one. UDPRoute's lack of hostname-based matching means this is a capacity decision, not a routing detail.
Getting the route-type family standardized now — HTTPRoute, TLSRoute, TCPRoute, and UDPRoute all on the same GatewayClass — is exactly the lesson this blog's own Ingress-NGINX retirement post already drew from a different angle: doing a disciplined migration once, on your own schedule, beats getting forced into a second one later because half your fleet's traffic never had a real routing story to begin with.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, all routed through the same Gateway API stack this post describes. Star the repo on GitHub or deploy your first app today.
Sources
- Gateway API v1.6.0 release notes
- Gateway API v1.6 implementation status
- Gateway API resource reference (GA status per type)
- Announcing Envoy Gateway v1.7
- Envoy Gateway UDP routing guide
- Cilium TCPRoute/UDPRoute dataplane feature request
- Gateway API hostnames concept (HTTPRoute/TLSRoute vs. UDPRoute matching)



