Skip to main content

Gateway API v1.5 Moves Six Features to Stable: Which Ones Your Git-Push PaaS Should Adopt First

8 min readDora NodaDora Noda
Share
On this page

Six promotions, one verdict table, and a migration checklist: Gateway API v1.5 — released February 27, 2026 and written up on the Kubernetes blog on April 21 — is the project's biggest stabilization release yet, moving ListenerSet, TLSRoute, the HTTPRoute CORS filter, frontend client-certificate validation, backend TLS-origination certificate selection, and ReferenceGrant onto the Standard (GA) channel. If your platform's per-tenant routing still lives in an Ingress controller's annotation dialect, this is the release that makes the typed alternative boring enough to bet on.

Here is the payoff up front — every one of the six, mapped to the git-push routing need it serves, with an adopt-now-or-later verdict. The rest of the post substantiates each row.

#Newly stable in v1.5Git-push PaaS need it servesVerdict
1ListenerSetPer-tenant listeners and custom domains without editing the shared GatewayAdopt now
2TLSRouteSNI routing for tenants with their own certs or raw TCP servicesAdopt now if you terminate per-tenant TLS
3HTTPRoute CORS filterTyped CORS for SPA-plus-API tenants, no annotation blobAdopt now
4Frontend client-cert validationmTLS at the edge for zero-trust tenant APIsPilot on one listener
5Backend TLS-origination cert selectionGateway presents a client cert to backends (full mTLS loop)Pilot with #4
6ReferenceGrant v1Cross-namespace routing on a no-breaking-changes contractAdopt now (you likely already use it)

Two honest caveats before the detail. First, the header-based routing and weighted traffic splitting your preview environments need are long-stable HTTPRoute core, not part of these six — they get a section anyway, because they are the foundation the six join, and any honest accounting of "what does the stable channel buy my edge" has to include them. Second, v1.6 (August 2026) has since graduated TCPRoute and UDPRoute too, so the "which channel?" question keeps shrinking.

Delegating the front door: ListenerSet and ReferenceGrant v1

Before ListenerSet, every listener lived inline on the Gateway object. For a single team that is fine. For a platform it means the Gateway is a shared file that the platform team and every tenant's automation must coordinate writes to — or, more commonly, the platform team owns the Gateway and tenants get whatever listeners already exist. ListenerSet (GEP-1713) fixes this by letting listeners be defined independently and merged onto a target Gateway, with the platform controlling who may attach via allowedListeners.

Concretely, the platform keeps a small Gateway with a default HTTP listener, and each tenant namespace contributes its own HTTPS listener — hostname, port, and certificate reference included — without touching the shared object:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata: {name: paas-edge, namespace: infra}
spec:
  gatewayClassName: paas-edge
  allowedListeners:
    namespaces: {from: All}
  listeners:
    - {name: http, protocol: HTTP, port: 80}
---
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata: {name: tenant-acme, namespace: tenant-acme}
spec:
  parentRef: {name: paas-edge, namespace: infra}
  listeners:
    - name: https-acme
      protocol: HTTPS
      port: 443
      hostname: acme.onbex.co
      tls: {certificateRefs: [{name: acme-cert}]}

Two details matter operationally. The Gateway's own listeners field stays mandatory — it must keep at least one valid listener — so the platform always retains a baseline it owns. And ListenerSets lift the practical ceiling past 64 listeners on one shared Gateway, which is exactly the wall a custom-domain-per-tenant platform hits first: dozens of hostnames, each needing its own listener, all on one edge.

ReferenceGrant's promotion is quieter but load-bearing for the same architecture. It is the object that permits a route in namespace A to reference a backend or secret in namespace B — the cross-namespace edge every multi-tenant platform draws constantly. It had not changed in over a year, so v1.5 simply stamped it v1 with the GA no-breaking-changes contract. If your controllers already create ReferenceGrants, this row costs you nothing and buys you a stability promise; if you have been avoiding cross-namespace routing because the API felt provisional, the excuse just expired.

TLS, end to end: TLSRoute and the mTLS pair

TLSRoute (GEP-2643) routes by the SNI hostname presented during the TLS handshake and sends the stream to a Kubernetes backend. A Gateway TLS listener runs in one of two modes, and the choice is a clean decision rule for a platform:

  • Passthrough: the encrypted byte stream goes straight to the backend. The Gateway never sees keys or plaintext. Use it when the tenant owns the certificate relationship end to end, when client and backend must authenticate directly, or when the workload is an encrypted TCP stream rather than HTTP.
  • Terminate: the Gateway ends the TLS session and forwards decrypted TCP to the backend. Use it for centralized certificate management — one place to rotate certs — at the cost of plaintext on the last hop inside your network.
yaml
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata: {name: tenant-direct, namespace: tenant-acme}
spec:
  parentRefs: [{name: paas-edge, namespace: infra, sectionName: tls-passthrough}]
  hostnames: ["db-console.acme.example.com"]
  rules: [{backendRefs: [{name: console-svc, port: 8443}]}]

The migration warning here is real and specific: if you install v1.5 Standard over v1.4-or-earlier Experimental, existing Experimental TLSRoutes stop working, because v1alpha2 is not included in the v1.5 Standard YAMLs. Migrate manifests to TLSRoute v1 first — and note its CEL validation requires Kubernetes 1.31 or newer, a notch above the release's general 1.30 floor.

The other two TLS promotions close the mTLS loop around the Gateway. Frontend client-certificate validation (GEP-91) lets the Gateway demand a client certificate before a connection proceeds, validated against CA bundles in ConfigMaps, with AllowValidOnly as the default mode and a cautious AllowInsecureFallback that delegates authorization downstream. Configuration applies Gateway-wide with per-port overrides, so one listener can require mTLS while the rest stay public.

Backend TLS origination (GEP-3155) is the mirror image: tls.backend.clientCertificateRef gives the Gateway a client certificate to present to backends, so a tenant backend accepts connections only from the platform's edge. Adopt these two as a pair on one listener first — half an mTLS loop is just latency with extra steps — and only then roll them across the fleet.

HTTPRoute grows up: CORS, header matches, and preview splits

The HTTPRoute CORS filter (GEP-1767) replaces the most copy-pasted annotation blob in multi-tenant ingress: per-route CORS policy expressed as controller-specific strings. The stable filter is typed — allowOrigins (including https://*.bar.com semiwildcards), allowMethods, allowHeaders, exposeHeaders, allowCredentials, and maxAge — so a typo fails validation instead of silently shipping an open or broken policy:

yaml
rules:
  - matches: [{path: {type: PathPrefix, value: /api}}]
    backendRefs: [{name: api-svc, port: 8080}]
    filters:
      - type: CORS
        cors:
          allowOrigins: ["https://app.acme.example.com"]
          allowMethods: [GET, POST, OPTIONS]
          allowCredentials: true
          maxAge: 3600

That leaves the two routing primitives every preview-environment design leans on: header-based routing and traffic splitting. Both are long-stable HTTPRoute core — matches on headers and weighted backendRefs predate v1.5 by a long way — which is precisely the point. The weighted split below is the entire machinery behind "send 5% of production traffic, or all traffic carrying the preview header, to the ephemeral environment," and it has been portable across implementations while Ingress users reimplemented it per controller:

yaml
rules:
  - matches:
      - headers: [{name: x-preview-env, value: pr-4821}]
    backendRefs: [{name: web-pr-4821, port: 8080}]
  - backendRefs:
      - {name: web-prod, port: 8080, weight: 95}
      - {name: web-pr-4821, port: 8080, weight: 5}

The honest Ingress comparison, then: a rewrite that was nginx.ingress.kubernetes.io/rewrite-target becomes an HTTPRoute urlRewrite filter; a canary that was a second Ingress plus annotation magic becomes weights on backendRefs; CORS that was five annotations becomes one typed filter. None of this is new in v1.5. What v1.5 changes is the size of the stable surface around it — six fewer reasons to keep one foot in Experimental or one controller's dialect.

The migration checklist (and what to adopt first)

Moving a platform edge is a rollout, not a flag flip. The checklist, with concrete versions:

  1. Install the Standard channel CRDs at v1.5.1 (the patch release is already out) and confirm your controller's conformance claim names v1.5 — seven implementations were conformant at announcement: Agentgateway, Airlock Microgateway, GKE Gateway, HAProxy Ingress, kgateway, NGINX Gateway Fabric, and Traefik Proxy. For a self-hosted fleet, the Envoy-based options (kgateway, NGINX Gateway Fabric) and Traefik are the natural shortlist.
  2. Migrate any Experimental TLSRoutes to v1 before switching channels, or stay on Experimental until you do. This is the one sharp edge in the release.
  3. Check the Kubernetes floor: 1.30 generally, 1.31+ wherever TLSRoute's CEL validation runs.
  4. Pick the controller by profile, not habit. The conformance suite now covers the six, so "does it implement ListenerSet and the CORS filter?" is an answerable question per implementation instead of a source-code spelunking trip.
  5. Watch v1.6 for TCP/UDP: if your tenants need raw TCP or UDP routing, TCPRoute and UDPRoute are now Standard as of the August 2026 v1.6 release — one more Experimental dependency you can delete.

One process note favors planning around this release: v1.5 moved the project to a release-train model with dedicated Release Manager roles, so future promotions should land on a steadier cadence instead of bunching into irregular mega-releases. For a platform team scheduling edge upgrades quarters ahead, a predictable train beats a surprise bundle.

Adopt in this order: ReferenceGrant v1 (free), ListenerSet (unlocks tenant self-service on listeners), the CORS filter (deletes annotation sprawl route by route), TLSRoute (whenever per-tenant TLS or TCP arrives), and the mTLS pair as a piloted unit. Each step is independently revertible, which is the real luxury a stable channel buys: you can move one row of the table at a time instead of betting the edge on a channel that makes no compatibility promises.

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex