Skip to main content

Gateway API v1.5 Makes TLSRoute and Gateway mTLS Stable: What Your Self-Hosted PaaS Gets for Free

8 min readDora NodaDora Noda
Share
On this page

On February 27, 2026, the Kubernetes SIG Network community shipped Gateway API v1.5 — self-described as its biggest release yet, and one with a single theme: moving existing Experimental features to Standard. Six promotions crossed the GA line at once, and two of them land directly on the TLS story every self-hosted PaaS has been duct-taping together with Ingress annotations for years: TLSRoute is now v1 in the Standard channel, and Gateway-level client certificate validation — frontend mTLS — is stable alongside it.

If you run a git-push platform on machines you own, this is the release that turns "we route TLS with a pile of implementation-specific annotations" into "we route TLS with portable, GA Kubernetes APIs." But stable spec and turnkey operations are not the same thing. Here is what v1.5 concretely gives you, the YAML you can now write, the upgrade trap that will bite you if you skip the changelog, and the gaps that remain before any of it is boring.

What v1.5 actually stabilized​

The release promotes six features to the Standard channel — Gateway API's GA contract, meaning no breaking changes from here on. You do not need a Kubernetes upgrade to get them: anything running 1.30 or later can install the v1.5 CRDs.

PromotionWhat it isWhy a PaaS operator cares
TLSRoute v1SNI-based TLS routingStable passthrough for tenants that own their certs
Gateway client-cert validationFrontend mTLS on the GatewaymTLS without bolting on a service mesh
Backend client certificateGateway identity for upstream mTLS (GEP-3155)Backends can verify the Gateway, not just the reverse
ListenerSetListeners defined outside the Gateway objectMulti-tenant listener scale past the 64-listener ceiling
HTTPRoute CORS filterFirst-class CORS policyOne less annotation dialect per implementation
ReferenceGrant v1Cross-namespace reference grantsUnchanged for a year; now under the GA contract

The release also switches the project to a release-train model — features ship when ready at freeze time — and a v1.5.1 patch is already out. Seven implementations were fully conformant at announcement time: Agentgateway, Airlock Microgateway, GKE Gateway, HAProxy Ingress, kgateway, NGINX Gateway Fabric 2.5.0, and Traefik. Note one name missing from that list — we will come back to it, because it is probably the one you run.

TLSRoute goes GA: SNI routing without the annotation soup​

The TLSRoute resource routes by matching the Server Name Indication (SNI) presented during the TLS handshake and directing the stream to a backend. A Gateway's TLS listener runs in one of two modes: Passthrough, where the Gateway never decrypts and routes the encrypted stream by SNI, or Terminate, where it decrypts and forwards plaintext. One nuance worth knowing: Terminate mode sits at the Extended support level, so check your implementation's conformance report before depending on it; Passthrough is the core GA path.

Here is the canonical passthrough shape, straight from the release, now under the v1 API version:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
spec:
  gatewayClassName: example-gateway-class
  listeners:
  - name: tls-passthrough
    protocol: TLS
    port: 8443
    tls:
      mode: Passthrough

and the route attached to that listener:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
  name: foo-route
spec:
  parentRefs:
  - name: example-gateway
    sectionName: tls-passthrough
  hostnames:
  - "foo.example.com"
  rules:
  - backendRefs:
    - name: foo-svc
      port: 8443

What does this replace? The classic self-hosted pattern for "tenant brings their own TLS" has been nginx.ingress.kubernetes.io/ssl-passthrough: "true" — an annotation that only works with NGINX Ingress, forces a specific controller, and famously cannot share port 443 sanely with terminated traffic. The pre-GA alternative was TLSRoute v1alpha2 from the Experimental channel, which worked but carried the alpha API warning: it could change or vanish. Now the SNI-routing primitive is portable across every conformant implementation and frozen under the GA contract.

The concrete PaaS use cases: tenant databases that terminate their own TLS, mTLS-required services where the backend must see the client handshake untouched, and legacy apps that own their certificates and cannot hand you the private key. Those workloads previously needed either a dedicated LoadBalancer per tenant or controller-specific hacks. With stable TLSRoute, they share one Gateway with everything else, routed purely on SNI.

Gateway-level mTLS: client certs without the mesh​

The second headline is frontend mTLS: the Gateway validates the client's certificate during the handshake against CA bundles you configure, before traffic ever reaches a backend. The API (GEP-91) was deliberately shaped to close a connection-reuse vulnerability — validating identity once at the edge rather than trusting a reused downstream connection — while keeping per-port flexibility.

Configuration lives in spec.tls.frontend, with a default for all HTTPS listeners plus per-port overrides:

yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: client-validation-basic
spec:
  gatewayClassName: acme-lb
  tls:
    frontend:
      default:
        validation:
          caCertificateRefs:
          - kind: ConfigMap
            group: ""
            name: foo-example-com-ca-cert
  listeners:
  - name: foo-https
    protocol: HTTPS
    port: 443
    hostname: foo.example.com
    tls:
      certificateRefs:
      - kind: Secret
        group: ""
        name: foo-example-com-cert

Two validation modes exist. AllowValidOnly (the default) accepts only connections presenting a certificate that validates against your CA bundle. AllowInsecureFallback also accepts missing or invalid client certs — delegating authorization to the backend — and the docs flag it as use-with-caution, which is exactly right: it is a migration ramp, not a posture.

The matching upstream half graduated too. GEP-3155 adds tls.backend.clientCertificateRef, the client certificate the Gateway presents when connecting to backends, so a backend can verify it is talking to your Gateway and not just any in-cluster caller. Frontend validation plus backend identity is the full mTLS loop, expressed in two Gateway fields instead of a mesh install.

For a self-hosted PaaS, the payoff is concrete: service-to-service auth and agent-to-infrastructure auth no longer need Istio or Linkerd bolted onto a fleet that adopted Gateway API precisely to avoid that weight. Internal listeners — your deploy API, your agent sandbox control plane — can require client certs at the edge, with the Gateway populating the standard x-forwarded-client-cert header for backends that want the identity downstream. The Kuadrant project already recommends v1.5 frontend validation as its Tier 1 mTLS approach where the implementation supports it.

The upgrade gotcha: read this before you bump the CRDs​

Here is the trap, quoted nearly verbatim from the release notes because it deserves it: if you install the v1.5 Standard channel over v1.4-or-earlier Experimental, your existing Experimental TLSRoutes will stop working. They are stored as v1alpha2 (or v1alpha3), which is not included in the v1.5 Standard YAMLs. Either stay on the Experimental channel or migrate your TLSRoutes to v1 first. And the clock is ticking: v1alpha2 is removed entirely in v1.6.

This is not theoretical. Envoy Gateway — the implementation a large share of self-hosted Gateway API users actually run, and conspicuously absent from the seven conformant-at-announcement implementations — hit exactly this seam. Issue #8326 tracked TLSRoute reconciliation silently skipping on Standard-channel clusters, and Envoy Gateway 1.8.0 requires Gateway API v1.5.1, crash-looping with no matches for kind "TLSRoute" in version "gateway.networking.k8s.io/v1" if the CRDs are not bumped first. NGINX Gateway Fabric 2.5.0 (March 30, 2026) and Cilium 1.20 (already moved on to v1.6, where TCPRoute and UDPRoute graduated) show the ecosystem converging — but "converging" means you must check your implementation's compatibility matrix, not assume it.

The safe upgrade order: audit for v1alpha2/v1alpha3 TLSRoutes, confirm your implementation's v1.5 support and required CRD version, bump CRDs, then migrate the routes to v1. Do it in that order and it is uneventful; do it in any other order and your SNI routing goes dark.

What is still not turnkey​

Stable spec, yes. Boring operations, not quite. Three gaps remain for the typical small-team stack:

cert-manager's Gateway API support is still beta. The feature has been flag-free since cert-manager 1.15, but it remains officially beta, ListenerSet support only arrived in v1.20, and TLS-only ListenerSets needed the v1.21 HTTP01 parentRef-fallback annotation to share an HTTP listener for ACME challenges. Treat certificate issuance and DNS records as the integration surface to verify — the Gateway side is GA, the issuance automation riding on top of it is younger. If you run cert-manager below v1.21 with ListenerSets, budget an upgrade before you depend on the combination.

Implementation support is uneven. Seven conformant implementations at announcement is genuine momentum, but the long tail — including the Envoy Gateway versions most fleets still run — caught up over the following months, not on day one. Conformance reports, not release dates, are the source of truth for whether your build supports frontend validation or TLSRoute v1.

Terminate mode and per-port overrides are the sharp edges. TLSRoute Terminate is Extended support, and per-port mTLS overrides multiply the validation paths you must test. The GA contract covers the API shape, not every implementation's behavior at the corners. Pilot frontend mTLS on one internal listener with AllowValidOnly before rolling it across tenant-facing ports.

Your Monday-morning checklist​

Concretely, for a Cluster-API-managed fleet running Gateway API today:

  1. Inventory alpha routes. kubectl get tlsroutes -A -o yaml | grep apiVersion — anything v1alpha2/v1alpha3 must migrate to v1 before v1.6 removes the old versions.
  2. Check your implementation's matrix. Confirm the exact Gateway API CRD version your controller build wants (Envoy Gateway 1.8.0 wants v1.5.1) and whether it implements frontend validation.
  3. Bump CRDs, then migrate routes. In that order — the reverse strands Standard-channel clusters with unserved route versions.
  4. Pilot mTLS on one internal listener. Put AllowValidOnly on a deploy-API or agent-control-plane listener with a ConfigMap CA bundle; keep tenant traffic untouched until the XFCC plumbing is proven.
  5. Verify the cert-manager path. If you use ListenerSets, confirm v1.20+ (v1.21+ for TLS-only ACME); watch the beta surface, not just the GA Gateway.

Gateway API v1.5 is the release where the project's TLS story stops being "promising experimental" and starts being infrastructure you can build a platform on. The APIs are frozen, the YAML is portable, and the mTLS story no longer requires a mesh. What remains is ordinary operational diligence — version matrices, migration order, and the cert-issuance layer — which is exactly the kind of work a release like this is supposed to leave you with.

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