Stop reading whenever you have enough
Performance, in twelve questions.
Each one is the question the previous answer makes you ask. The ones that matter come with the command, because that is the part you meet at work.
Not technical? The first three questions are written for you, and they are enough to follow any conversation about this.
- Rungs
- 12
- Hands on
- 5
- Read
- ~8 min
What it costs
01–03Every call pays a small toll at each proxy. Whether that matters depends entirely on your numbers.
the honest bill, in numbers · for anyone defending or attacking the mesh
- 01
What does one hop through a proxy cost?
Not knowing this costs
The same toll is invisible to one system and fatal to another.
- Rough order: a fraction of a millisecond to a few
- Two proxies per call: yours and theirs
- Against a 100ms service call, noise. Against 2ms, not
- 02
Where does proxy memory go?
Not knowing this costs
A thousand service mesh makes every tiny pod carry a phonebook.
- Mostly config: every service the proxy knows about
- Default: every proxy knows the entire mesh
- Memory grows with mesh size, not pod traffic
- 03
When does the toll actually matter?
Not knowing this costs
Most meshes never hit any of the three, and tune anyway.
- Deep call chains: tolls stack per hop
- Single digit millisecond latency budgets
- Very high request rates on small pods
Before you scroll on
0/3You should now be able to
Measuring before touching
04–05Tuning without a baseline is redecorating in the dark.
the baseline, or nothing else counts · for whoever owns the tuning ticket
- 04
What is the proxy’s share of my latency?
hands onNot knowing this costs
Without this number, tuning success is unfalsifiable.
- Compare total duration against upstream service time
- The difference is the mesh share, per request
shellthe mesh share, from real traffickubectl logs deploy/checkout -c istio-proxy -n checkout --tail=200 \ | awk '$12 ~ /^[0-9]+$/ && $13 ~ /^[0-9]+$/ { sum += $12 - $13; n++ } END { if (n) print sum/n " ms mesh share avg over " n " requests" }' # 1.2 ms mesh share avg over 183 requests <- measured, not estimatedIn the default access log, field 12 is total duration and field 13 is upstream service time, both plain positional numbers. Set a custom accessLogFormat and these column numbers move, which is the usual reason this one-liner prints nothing. - 05
What are the proxies costing in CPU and memory?
hands onNot knowing this costs
The mesh bill hides in per pod slices nobody sums.
- They are containers: kubectl top sees them
- Sum them: the fleet cost is the real bill
shellthe fleet billkubectl top pods -A --containers | awk '$3=="istio-proxy" {cpu+=$4; mem+=$5; n++} END {print n " proxies, ~" cpu "m CPU, ~" mem "Mi memory total"}' # 412 proxies, ~8600m CPU, ~19000Mi memory totalNineteen gigabytes of phonebooks is the rung 2 problem, fleet wide. It is also the before number for the Sidecar resource fix below.
Before you scroll on
0/3You should now be able to
The two big knobs
06–07One knob shrinks what every proxy must know. One matches proxy threads to real load. Together they are most of tuning.
the settings that actually move numbers · for whoever operates a large mesh
- 06
How do I shrink what every proxy knows?
hands onNot knowing this costs
The single biggest memory lever in large meshes, and the most skipped.
- A Sidecar resource scopes egress per namespace
- Proxies get config for dependencies, not the world
- Memory and push load drop together
manifestthe phonebook, trimmedapiVersion: networking.istio.io/v1 kind: Sidecar metadata: name: default namespace: payments spec: egress: - hosts: - "./*" # own namespace - "checkout/*" # actual dependencies only - "istio-system/*"The trap: a dependency missing from this list becomes unreachable, exactly like exportTo hiding. Roll it out namespace by namespace with the egress inventory in hand. - 07
How do proxy resources get right sized?
hands onNot knowing this costs
Default proxy sizing is wrong in both directions at once across a fleet.
- Set requests from measured usage, not templates
- concurrency matches worker threads to CPU allotment
- Per pod annotation or mesh wide default
manifestsizing, per workload where it matters# pod template annotations: metadata: annotations: sidecar.istio.io/proxyCPU: "200m" sidecar.istio.io/proxyMemory: "192Mi" proxy.istio.io/config: | concurrency: 2concurrency 0 means match the CPU limit, which is right when a limit exists. Two worker threads saturating a 200m request is the common misfit on small pods.
Before you scroll on
0/3You should now be able to
The small knobs
08–09Telemetry volume and connection reuse: real, smaller, and cheap to try.
the second tier, applied when measured · for whoever is still not done
- 08
What does telemetry volume cost?
hands onNot knowing this costs
Telemetry is the cost you configured by not configuring it.
- Every metric label set is series cardinality
- Every access log line is CPU and storage
- Trim per namespace with the Telemetry API
manifestlogs off where they are pure costapiVersion: telemetry.istio.io/v1 kind: Telemetry metadata: name: quiet-hot-path namespace: adserving spec: accessLogging: - providers: - name: envoy disabled: trueA hot path at thousands of requests per second pays real CPU for log lines nobody reads. Keep logs on everywhere humans debug, off where only volume lives. - 09
Which knobs are usually not worth touching first?
Not knowing this costs
Deep tuning before scoping config is polishing the wrong surface.
- Exotic Envoy filters and hand tuned buffers
- Protocol tweaks before the two big knobs
- Anything you cannot tie to the rung 4 number
Before you scroll on
0/3You should now be able to
Where it ends
10–12At some point the mesh is not your bottleneck, and knowing when is the skill.
the limits, where people get caught · for whoever reviews the effort
- 10
When does proxy tuning stop paying?
Not knowing this costs
Past this line, tuning the mesh is avoiding tuning the app.
- When mesh share is small against app latency
- When the fleet bill is small against app resources
- Both are measurements you already have
- 11
What if the toll is genuinely too high?
Not knowing this costs
A latency budget the sidecar cannot meet is a design conversation.
- Ambient mesh moves proxying off the pod
- Or selectively unmesh the extreme path
- Both are architecture changes, not knobs
- 12
What do I write down when tuning ends?
Not knowing this costs
Undocumented tuning gets re litigated at every capacity review.
- The baseline, the knobs applied, the deltas
- The knobs considered and rejected, with numbers
- The next person inherits conclusions, not folklore
Before you scroll on
0/3You should now be able to
Go deeper
4 links, each earning its place.
Istio performance and scalability↗
The project’s own numbers behind rung 1, and how they were measured.
Sidecar resource reference↗
The scoping resource from rung 6, every field.
Proxy resource annotations↗
The per pod sizing surface from rung 7, complete.
Ambient mesh↗
The architecture level answer from rung 11, when knobs are not enough.