Performance Best Practices
Optimization decision tree and when to stop tuning.
Search across all documentation pages
Optimization decision tree and when to stop tuning.
Apply these rules in design reviews, incident postmortems, and optimization PRs so the team measures first, changes one variable at a time, and stops when SLOs are met.
go test -bench / benchstat output for library changes. Micro claims need micro proof.GOMAXPROCS, and load generator settings in PRs. Numbers without context are not reproducible.net/http is often your handler.alloc_space when GC or tail latency matters. Allocation churn drives pause frequency.-gcflags=-m) when benchmem shows surprise allocs. Compiler facts beat guessing.make([]T, 0, n) and map hints reduce growth copies.strings.Builder in loops. Avoid += concatenation in hot middleware.sync.Pool only after measured alloc wins. Pools add complexity and stale-state risk.[]byte. Memory spikes become GC events under load.default.pgo on release trains for stable CPU-bound binaries. Stale profiles misguide the compiler.GOMEMLIMIT near pod memory limits before OOM incidents repeat. Soft limit triggers earlier GC, not magic capacity.GOGC in canaries with p99 and CPU guardrails. Document rollback env vars in the runbook./debug/pprof is a security and DoS risk.Transport per upstream. http.DefaultClient has no timeout.GOMAXPROCS with container CPU quota. Runnable queue latency shows up in traces when mismatched.unsafe and //go:noinline as reviewed exceptions. Require ADR or benchmark evidence.Tier A through C should be satisfied before Tier D experiments ship to production.
If p99 latency, error rate, and cost metrics meet agreed SLOs, defer further optimization until the next measured regression.
Clarity wins default review unless evidence shows a hot path exception.
Profiles or benches for optimization-only PRs, no public pprof, and documented rollback for GC env changes are common merge blockers.
Performance Rules: When to Optimize is the cheatsheet policy.
This list is the operational checklist for teams executing that policy.
Cosmetic or cold-path changes with no performance claim.
Any PR advertising speed or latency improvements needs evidence.
Measurement work is encouraged.
Merging hot-path rewrites or GC tuning should include review from someone who can read pprof and trace output.
sync.Pool and manual inlining before heap profiles prove allocation or CPU hotspots.
Measure first.
When release branches cut or when CPU flat graphs shift after major features.
Stable services often refresh monthly or per release.
Measure-first culture applies.
Profiling tooling differs - verify board and runtime constraints at build time per manifest pins.
Yes for benchmarks on critical packages, lint banning http.Get in handlers, and staging load gates.
GC tuning remains a manual canary step.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026