If you’ve deployed a Go service to Kubernetes and set careful CPU and memory limits on your pod, there’s a good chance your Go runtime was ignoring them entirely — spawning too many threads, running GC on the wrong schedule, and getting throttled or OOM-killed as a result.

Go 1.25 fixed half of this problem natively. This post explains both halves: what was broken, what’s fixed, what’s still not fixed, and what to do if you can’t upgrade yet.

The problem: Go doesn’t know it’s in a container

When a Go program starts, the runtime reads the host machine’s CPU count and sets GOMAXPROCS — the number of OS threads that can run Go code in parallel — to that number. On a 64-core Kubernetes node, your Go service thinks it has 64 CPUs available, even if your pod’s resource limit is cpu: "2".

The same problem exists for memory. Go’s garbage collector uses a target heap growth ratio (controlled by GOGC) to decide when to trigger collection. By default, it allows the heap to double before collecting. If your container has a 512 MB memory limit and the Go runtime doesn’t know about it, the GC may allow heap growth that pushes your process past the cgroup limit before it triggers a collection. The result: an OOM kill.