Istio Ambient cuts the sidecar tax at L4, but L7 adds waypoint hops, and Linkerd stable builds now come from Buoyant. Choose with tests.
Your platform team finally gets budget to roll out mTLS across 400 services. Someone pulls up a 2023 comparison: Istio has features, Linkerd has simplicity, both charge you a sidecar tax. Then Istio Ambient went GA and a wave of posts declared the simplicity argument dead.
That conclusion skips the two things that actually decide a 2026 evaluation: what happens to your request path when you turn on L7 features, and how each project now handles production releases. This post covers both, with commands you can run in a test cluster before you commit.
The real difference is topology. Istio Ambient uses two data-plane tiers (a per-node ztunnel for L4 and an optional waypoint proxy for L7), while Linkerd uses one per-pod proxy for everything. Turning on L7 features changes Istio's request path and only changes Linkerd's configuration.
Neither design is better in every case. The Istio design lets you pay for L7 only on services that need it. The Linkerd design gives you one thing to reason about at 3am.
For L4 traffic, yes. Ambient runs a ztunnel as a DaemonSet, one per node, which handles mTLS, identity and L4 authorization for every pod on that node. You no longer pay an Envoy container, often tens of megabytes of memory each, multiplied by your pod count.
Ambient mode reached GA in Istio 1.24. Enrolling a namespace needs one label and no pod restarts:
## enroll a namespace in ambient modekubectl label namespace payments \ istio.io/dataplane-mode=ambient ## confirm ztunnel runs on every nodekubectl get pods -n istio-system -l app=ztunnel -o wideThe catch is that most teams adopt a mesh for L7 features: retries, timeouts, per-route metrics, canary traffic shifting and HTTP-aware authorization. None of those run in ztunnel. They need a waypoint.
A related trap: an authorization policy that matches on HTTP methods or paths cannot be enforced by ztunnel, which only sees L4. Attach such policies to a waypoint, and check the Istio ambient docs for how your version treats L7 rules that have no waypoint to run on.
A waypoint is an Envoy-based proxy deployed through the Kubernetes Gateway API, scoped to a namespace or a single service. It adds a second data-plane tier that you size, scale, upgrade and monitor separately from ztunnel.
## deploy a waypoint and enroll the whole namespaceistioctl waypoint apply -n payments --enroll-namespace ## check the waypoint gateway is programmedkubectl get gateway -n paymentsistioctl waypoint status -n paymentsUnder the hood this creates a standard Gateway resource using the istio-waypoint class, which is why the waypoint is managed like any other Kubernetes workload:
apiVersion: gateway.networking.k8s.io/v1kind: Gatewaymetadata: name: waypoint namespace: payments labels: istio.io/waypoint-for: servicespec: gatewayClassName: istio-waypoint listeners: - name: mesh port: 15008 protocol: HBONEOnce a service is enrolled, traffic to it goes ztunnel to waypoint to ztunnel. During an incident, "which hop added latency" now has several candidate answers in each direction, and the waypoint can become a hot spot if it is under-replicated.
Budget for three recurring costs:
Tip: scope waypoints per service account instead of per namespace when only a few services need L7. You pay for the extra tier only where it earns its keep.
Run the same load test against one service twice, once through the waypoint and once with the waypoint label removed. The difference in p99 is the price of L7 for that service, measured on your hardware with your traffic.
## attach a service to the waypointkubectl label svc echo -n bench istio.io/use-waypoint=waypoint ## run the load test, note p99, then detach itkubectl label svc echo -n bench istio.io/use-waypoint- ## run the same load test again and compareThe trailing - in the second command removes the label. If the waypoint shows a large p99 jump, check its replica count and CPU requests before concluding the design is slow. A single under-sized waypoint replica is the usual cause.
The source is still Apache 2.0, but the release model changed. In early 2024, Buoyant, the company that maintains Linkerd, stopped publishing open source stable releases starting with Linkerd 2.15. Stable, production-supported builds now come through Buoyant Enterprise for Linkerd, which is free for smaller companies and paid above a size threshold (50 employees when the change was announced). The fully free path is edge releases, which you vet and support yourself.
This has the same shape as the Terraform and OpenTofu story: a project maintained mainly by one vendor tightened how production releases are distributed. The difference is that there is no widely adopted fork of Linkerd's stable channel as of this writing.
Your realistic options are:
Important: check Buoyant's current pricing and eligibility terms before you decide. This is the part of the comparison most likely to have changed since this post was written.
Linkerd's Rust proxy has generally shown lower latency and memory overhead than Envoy-based data planes in published tests, and Ambient narrows the gap at L4. Treat every published number as directional: the benchmarks come from the projects' own maintainers or vendors, they use different methods, and the gap depends heavily on which L7 features you enable.
A minimal method that gives you comparable numbers:
## baseline: no meshfortio load -c 64 -qps 1000 -t 120s \ -p "50,90,99,99.9" http://echo.bench.svc:8080/ ## repeat the same command with the mesh enabled## compare p99 and p99.9, not the averageRun it three ways for Istio (L4 only, with a waypoint, with a waypoint plus a retry policy) and two ways for Linkerd. Also record memory per node using kubectl top over the whole run. The p99.9 delta under sustained load is usually more telling than any static benchmark table.
For Linkerd, the setup is one annotation per namespace, and golden-signal metrics come from the viz extension:
## inject the proxy into new pods in a namespacekubectl annotate namespace payments linkerd.io/inject=enabled ## verify the install, then read success rate and latencylinkerd checklinkerd viz stat deploy -n paymentsExisting pods only get the proxy after a restart, so run a rolling restart of each deployment after annotating.
Architecture and operations:
| Factor | Istio Ambient | Linkerd |
|---|---|---|
| L4 data plane | ztunnel per node | Proxy per pod |
| L7 data plane | Adds waypoint tier | Same proxy |
| Topology at L7 | Extra hop | Unchanged |
Licensing and ecosystem:
| Factor | Istio | Linkerd |
|---|---|---|
| Stable releases | Fully open source | Buoyant subscription |
| VM workloads | Supported | Kubernetes focused |
| Ingress | Gateway API | External controller |
Istio still supports classic sidecar mode, so teams that need the most mature L7 path today can keep sidecars on a few services and use Ambient for the rest. If neither fits, Cilium's service mesh features are worth a look when you already run Cilium as your CNI and mainly need mTLS and L4 policy.
Choose Istio Ambient if you need advanced L7 control such as fault injection, request mirroring, JWT-aware authorization or Wasm extensibility. Also choose it if you run VMs next to Kubernetes, if you already know Envoy, or if procurement will not accept a subscription-gated stable channel.
Choose Linkerd if your core need is mTLS plus solid golden-signal observability with the smallest operational surface, and you have budgeted for Buoyant Enterprise or for owning edge releases.
Before you commit, run this three-step evaluation:
The tabletop surfaces the waypoint trade-off far more clearly than any benchmark chart. Record the Istio and Linkerd versions you tested, because both projects ship changes that move these results.
References and Further Reading
- Istio Ambient Mode Overview - Official architecture of ztunnel and waypoints
- Linkerd Releases and Versions - Official release channels and support model
- Kubernetes Gateway API - The API Istio uses to deploy waypoints
- Fortio Load Testing Tool - The tool used in the benchmark method above
For L4 traffic, mostly yes: the ztunnel DaemonSet handles mTLS and L4 policy once per node instead of running one Envoy per pod. L7 features such as retries, route-level metrics and canary splits still need a waypoint proxy tier, so the tax only disappears fully for L4-only use cases.
The source code stays Apache 2.0, but since Linkerd 2.15 (2024) Buoyant no longer publishes open source stable releases. Production-supported stable builds come through Buoyant Enterprise for Linkerd (free below a company-size threshold, paid above it), while the free path is edge releases you vet and support yourself. Check Buoyant's current terms before deciding.
Linkerd's proxy sits beside every pod, so the path is always proxy to proxy and L7 features are configuration only. In Ambient, L7 policy runs in a waypoint proxy, so the path grows from ztunnel to ztunnel into ztunnel to waypoint to ztunnel for enrolled services.
Compare p99 for the same call with and without the waypoint by removing the istio.io/use-waypoint label from one test service with kubectl label svc NAME istio.io/use-waypoint-. Then read waypoint Envoy stats and check ztunnel logs to see which hop added the delay, and check whether the waypoint is under-scaled.
As of this writing there is no widely adopted fork of Linkerd's stable channel. Teams realistically choose between a Buoyant subscription, building and supporting edge releases themselves, or moving to Istio or Cilium.
Discussion0