Problem Statement
Your Go service runs in a 2GB container but keeps getting OOM killed. Configure GOMEMLIMIT and GOGC to prevent this while maintaining performance.
GOGC (Garbage Collection Percentage)
// GOGC=100 (default): GC triggers when heap doubles
// GOGC=50: GC triggers when heap grows 50%
// GOGC=200: GC triggers when heap triples
import "runtime/debug"
func init() {
debug.SetGCPercent(50) // More frequent GC, less memory
}
// Or via environment:
// GOGC=50 ./myappGOMEMLIMIT (Go 1.19+)
import "runtime/debug"
func init() {
// Soft memory limit - GC becomes aggressive near limit
debug.SetMemoryLimit(1.5 * 1024 * 1024 * 1024) // 1.5GB
}
// Or via environment:
// GOMEMLIMIT=1500MiB ./myappContainer Configuration
# Kubernetes deployment
containers:
- name: myapp
resources:
limits:
memory: 2Gi
env:
- name: GOMEMLIMIT
value: "1800MiB" # Leave headroom for OS
- name: GOGC
value: "100"The Old Ballast Technique (Obsolete)
// Before GOMEMLIMIT, teams used "ballast":
var ballast = make([]byte, 10<<30) // 10GB unused allocation
// This tricked GC into running less often
// Now obsolete - use GOMEMLIMIT insteadDebugging Memory Issues
# Enable GC tracing
GODEBUG=gctrace=1 ./myapp
# Output example:
# gc 5 @0.5s 2%: 0.5+2.0+0.5 ms clock, 4.0+0/2.0/0+4.0 ms cpu,
# 4->5->2 MB, 5 MB goal, 4 P
# Meaning:
# 4->5->2 MB = heap before GC -> after GC -> live data
# 2% = percentage of CPU spent on GCBest Practices
- Set GOMEMLIMIT to 80-90% of container memory
- Leave room for OS file cache and overhead
- Monitor with
runtime.ReadMemStats() - Use pprof heap profiles to find allocations