A service mesh sidecar is a second container riding shotgun in every single pod, terminating TLS, enforcing policy, and burning CPU whether or not the pod is doing anything interesting. A 2026 gRPC load-balancing benchmark measured Istio's sidecar proxy at roughly six times Linkerd's memory footprint for 27% more CPU, at identical throughput — and that's the cheaper of the two sidecar options. Cilium's pitch is that none of this is necessary at all: mutual TLS and workload identity enforced straight in the Linux kernel via eBPF, no sidecar, no per-pod proxy. That part of the claim holds up under the numbers. The part that doesn't get mentioned nearly as often: Cilium's own design-review process has documented a specific, exploitable auth-bypass condition in its mutual authentication feature, rooted in exactly the shortcut that makes it so cheap. For a multi-tenant platform running tenant workloads on shared nodes, that tradeoff is the actual story — not "sidecars are dead."
What a sidecar actually costs
Start with the number the sidecar model has to defend. Buoyant's own 2026 gRPC load-balancing benchmark put concrete resource numbers on the two most-deployed sidecar implementations: Linkerd's proxy ran about 0.22 CPU cores and 45MiB of memory per 1,000 RPS, while Istio's sidecar needed roughly 0.28 cores and 273MiB for the same throughput — six times the memory for 27% more CPU. That's proxy cost alone, before the application container it's riding alongside does any work. A separate real-world data point from LinkedIn's infrastructure team, migrating away from iptables-based sidecar redirection at 2M+ RPS scale, found that iptables redirect overhead alone was contributing roughly 8% of total CPU consumption cluster-wide — a number they cite as part of their own case for moving to Cilium's eBPF data path instead. Multiply the per-pod proxy cost by every pod in a multi-tenant fleet and the sidecar isn't a rounding error; a back-of-envelope figure often cited for a modest fleet — sidecars pinned at 100m CPU across 500 pods — works out to roughly 50 full cores of persistent compute, on the order of $2,000–$5,000 a month on standard cloud pricing, spent on proxies rather than tenant workloads.
Istio's own answer to this was Ambient mode, which reached general availability in November 2024 and replaced the per-pod sidecar with ztunnel — a single Rust-based proxy running once per node as a DaemonSet, handling mTLS and L4 policy for every pod on that node instead of one proxy per pod. Buoyant's benchmark measured the optional L7 waypoint proxy at about 0.12 cores and 226MiB per 1,000 RPS — lower than the sidecar's 0.28 cores on the CPU side, though Buoyant's own writeup flags that figure as the waypoint's L7 leg only; ztunnel's separate L4/mTLS cost for every pod on the node isn't included, so ambient's true total cost sits above the waypoint number alone. Even accounting for that, ambient mode is proof that "sidecarless" was already achievable without leaving TLS-on-the-wire behind: ztunnel still does a real mTLS handshake, per connection, for every pod-to-pod flow it forwards. That distinction matters for what comes next, because Cilium's version of sidecarless doesn't work quite the same way.
How Cilium does it without a proxy at all
Cilium skips the per-node proxy too, not just the per-pod one. Its eBPF programs run directly in the kernel's network data path: when a packet leaves a pod, the local Cilium agent intercepts it, performs a TLS handshake using automatically issued certificates, validates the peer's identity, and forwards the now-authenticated traffic — encrypted, if the deployment has WireGuard or IPsec transparent encryption turned on, or just authorized, if it doesn't. No sidecar container, no per-node proxy process outside the Cilium agent that's already running for networking and policy enforcement anyway. Identity issuance runs through SPIFFE and SPIRE: a central SPIRE server acts as the root of trust for the cluster's trust domain, a per-node SPIRE agent gets its own identity and then validates workload identity requests from Cilium, and Cilium registers each workload's Kubernetes-derived security identity with SPIRE without the application ever knowing any of this is happening. When the SPIRE server rotates its CA, it pushes the new trust bundle down to every agent, which pushes it to every workload. It's the same certificate-issuance-and-rotation machinery a full service mesh already runs — Cilium doesn't eliminate that operational surface, it just moves where the enforcement happens.
The mechanism requires a 5.10+ Linux kernel (or the equivalent backport most current distros ship), and as of Cilium 1.19–1.21, mutual authentication itself remains a Beta feature — not the default, and not yet the thing every Cilium deployment is running by default in production.
The catch: identity from a cache, not from the wire
Here's where the "sidecarless" pitch needs an asterisk it doesn't advertise. Cilium's mutual authentication doesn't maintain a TLS-encrypted state for the life of a connection the way a sidecar or ztunnel does. It uses the handshake to authenticate, then forwards plaintext (or WireGuard/IPsec-wrapped, if that's separately enabled) based on an identity Cilium looks up from a local cache mapping IP addresses to workload identities — the ipcache every node keeps to know which security identity owns which pod IP. That cache is, by Cilium's own design, eventually consistent. A pod's identity gets written to the ipcache when it starts; if that write lags, or if an IP gets reused before a stale entry clears, the node can momentarily attribute traffic to the wrong identity.
That gap isn't hypothetical. A security review credited to Solo.io, published through Cilium's own CFP-28986 design process, laid out the exact attack chain: it requires direct routing mode (no VXLAN/Geneve encapsulation, no WireGuard/IPsec encryption), a destination node that has temporarily lost connectivity to the Kubernetes API server (so its ipcache stops receiving pod-lifecycle updates), and an attacker who can schedule a new pod that reuses an IP address a previously authenticated pod used to hold. When those conditions line up, the destination node's stale cache attributes the new, unauthenticated pod's traffic to the old pod's already-trusted identity — a window bounded by how long the node stays disconnected or the certificate's lifetime (30 minutes by default), whichever ends first. In Cilium's encapsulated modes, or with WireGuard/IPsec transparent encryption turned on, the sending node stamps the actual security identity into every packet, so there's nothing for the receiving node to guess — the exploit path disappears because the ipcache stops being load-bearing. Cilium's own proposed fix is exactly that: require encryption or encapsulation so identity travels with the packet instead of being inferred from a cache that can go stale. No CVE has been assigned to this specific design gap as of this writing — it's tracked as an open design issue, not a patched vulnerability — which if anything makes it more worth knowing about before enabling the beta feature, not less. Until encryption or encapsulation is mandatory, "mutual authentication" is closer to "mutual authorization based on a cache that's usually right" than to end-to-end mTLS in the strict sense.
The New Stack's own writeup on this landed on a specific, actionable recommendation: layer Istio Ambient's ztunnel on top of (or instead of relying solely on) Cilium's mutual authentication, precisely because ztunnel enforces the mTLS handshake and encrypted channel on every connection regardless of IP address — it doesn't have an ipcache-shaped hole to fall through, because it never trusted the IP-to-identity mapping as the source of truth in the first place.
Closing the gap on the Cilium side doesn't require abandoning it — it requires not leaving encryption optional. Turning on WireGuard transparent encryption is a Helm-values change, not a redesign:
encryption:
enabled: true
type: wireguardWith that set, every node-to-node packet carries the sending node's actual security identity instead of asking the receiving node to reconstruct it from a cache that might be a few seconds stale. It's the difference between "identity is asserted in the packet" and "identity is inferred from a lookup table" — the same distinction that separates a bearer token from a session ID a server has to trust a cache to resolve correctly.
What this actually means for a multi-tenant fleet
For a self-hosted PaaS running tenant applications on a shared Cluster API-managed fleet — TLS terminated at the edge, tenant-to-tenant traffic inside the cluster otherwise unencrypted by default — the honest reading of all this is: adopt the eBPF approach, don't adopt it alone.
- What it buys: real east-west encryption and identity-based policy between tenant workloads without asking every tenant's pod to carry a second container, at a fraction of the CPU and memory a sidecar mesh would cost across a fleet running dozens of tenants per node. That's a genuine, load-bearing win for density — the whole reason a Hetzner-backed Cluster API fleet can pack tenants tightly in the first place is that the platform isn't paying a sidecar tax per workload on top of what each tenant's app already needs.
- What it doesn't buy for free: a security boundary you can point at and call done. Running in direct-routing mode with mutual authentication as the only tenant-isolation control repeats the exact configuration the CFP-28986 security review flagged as exploitable. The mitigation isn't exotic — turn on WireGuard or IPsec transparent encryption (which Cilium has supported outside the mTLS beta for years) so identity rides in the packet instead of a cache, and keep default-deny
CiliumNetworkPolicyas a second, independent layer rather than trusting identity-based mTLS as the sole gate between tenants. - What doesn't disappear: the SPIFFE/SPIRE certificate-issuance and CA-rotation machinery. "Sidecarless" describes where the enforcement runs, not whether a platform still owns a root of trust, a rotation schedule, and a blast radius if that root is ever compromised — the same operational responsibility a full Istio or Linkerd deployment already carries.
None of that makes kernel-enforced mTLS a bad bet — it's the correct default for a platform that's currently doing nothing between tenant pods beyond namespace boundaries and edge TLS. It just means the honest pitch isn't "sidecars are dead, ship it and move on." It's "the enforcement moved into the kernel, encryption or encapsulation has to be non-optional for it to mean anything, and the identity machinery you were trying to avoid is still exactly as much your problem as it always was."
Bex.co runs tenant workloads on a Cluster API-managed Hetzner fleet — an open-source, AI-native Render alternative where you own the machines instead of renting someone else's control plane. Star the repo on GitHub or deploy your first app today.
Sources
- How Cilium's Mutual Authentication Can Compromise Security — The New Stack.
- CFP-28986: Connection-based Mutual Authentication for Cilium Service Mesh.
- Mutual Authentication (Beta) — Cilium documentation.
- How to Implement Zero-Trust Workload Identity in Kubernetes with SPIFFE, SPIRE, and Cilium — freeCodeCamp.
- Benchmarking gRPC Load Balancing on Kubernetes in 2026: Linkerd vs Istio vs Cilium — Buoyant.
- Sidecarless mTLS in Kubernetes: How Istio Ambient Mesh and ztunnel Enable Zero Trust — Tigera.
- Istio Ambient overview — Istio documentation.
- Performance Comparison of Service Mesh Frameworks (arXiv).
- Service Mesh Performance Costs: The Reality of Sidecar Latency.



