collapser

A gRPC sidecar that collapses duplicate in-flight requests into one backend call.

I wrote this to learn how sidecars, Kubernetes and Istio actually behave rather than reading about them. This page is what I measured, including the parts I got wrong on the first pass.

What it does

When several callers ask a service the same question at the same time, the service answers it once per caller. The sidecar sits in front and gives them all the same answer from a single backend call.

The first request for a given key calls the backend. Anything arriving while that call is in flight waits on the same result instead of starting its own. A short result cache (100 ms) covers the gap just after a call finishes.

Envoy already does load balancing, retries and telemetry for this traffic, but it has no concept of two requests being the same request. That gap is the whole reason this exists.

Benchmarks

Three separate paths, benchmarked separately. Mixing them in one benchmark is the mistake I made first — see below.

PathTimeBytesAllocs
Cache hit45.7 ns0 B0
Joining an in-flight callbackend-bound54 B0
Leading a call1,594 ns552 B10
No sidecar (baseline)0.33 ns0 B0

Go 1.25.5, 11th Gen Core i7-1165G7, 8 threads. For the join path the number that means anything is allocations, not time — a waiter's wall clock is just however long the backend takes. Zero allocations there is the result of waiters sharing one channel instead of each registering their own.

Under load, in process

TestRequestsBackend callsErrors
10,000 concurrent, one key10,00020
60 s sustained, 100 workers391,4003920

Race detector on. Goroutine count and heap were flat across 100,000 requests.

On a cluster

Deployed to a local Kubernetes cluster (kind) with Istio 1.28.1, Envoy sidecars injected and mTLS set to STRICT. Backend calls counted by the backend itself, not by the sidecar reporting on its own work.

Concurrent requestsStraight to backendThrough sidecar
100100 calls1 call
500500 calls1 call
1,0001,000 calls1 call
2,0001 call

For the 2,000 run I checked three sources that don't depend on each other: the backend's own counter said 1, Envoy's istio_requests_total said 1, and the sidecar's metrics said 1.

What Istio saw

A load generator running inside the mesh, sending 600 concurrent requests spread over 25 distinct payloads every 250 ms. Both hops are reported by Envoy, so these are the mesh's numbers rather than mine.

Istio mesh dashboard in Grafana showing 1.42K requests per second total, with collapser-proxy receiving 1.36K req/s and hello-backend receiving 56.38 req/s, both at 100% success.
Istio mesh dashboard. The sidecar takes 1.36K req/s; the backend behind it sees 56 req/s. Same traffic, both measured by Envoy.
Kiali traffic graph showing loadgen sending traffic to collapser-proxy, which sends traffic to hello-backend, all edges healthy at 100 percent success.
Kiali, same window. The lock icons are Istio's mTLS between workloads — the sidecar itself speaks plaintext and never knows about it.

Over that run: 584,000 requests reached the sidecar and 24,304 reached the backend. The ratio is capped by how many distinct payloads the generator uses, not by the sidecar — with one payload it collapses to a single call.

What I got wrong

These were all in the version I had already written up before I went back and measured properly.

Limitations