What is GOMAXPROCS, what is its default, and what changed in Go 1.25 for containers?
Question 155MediumGo 1.22 to 1.25
GOMAXPROCS is the number of Ps, which is the maximum number of threads executing Go code at the same time. Threads blocked in syscalls or cgo do not count toward it. The default has been runtime.NumCPU() since Go 1.5. NumCPU respects the CPU affinity mask.
Before Go 1.25 the runtime ignored cgroup CPU quotas. A pod limited to 2 CPUs on a 64-core node got GOMAXPROCS=64. The result was CFS throttling, latency spikes and extra GC CPU. The usual workaround was go.uber.org/automaxprocs.
Go 1.25 (Linux) made the default container-aware:
- The default is the minimum of the core count (affinity mask) and the cgroup CPU limit, rounded up, with a floor of 2 (never above the CPU count). CPU requests are ignored.
- The runtime checks periodically and updates GOMAXPROCS if the limit or the affinity changes.
- Both behaviours turn off if you set the
GOMAXPROCSenvironment variable or callruntime.GOMAXPROCS(n).runtime.SetDefaultGOMAXPROCS()brings them back. - They depend on the
goversion in go.mod. You can control them withGODEBUG=containermaxprocs=0andupdatemaxprocs=0.
fmt.Println(runtime.GOMAXPROCS(0)) // 0 = query without changingMore on Goroutines & the Scheduler
- Q153What does this program do on Go 1.13 vs Go 1.14+?
- Q154How does a goroutine's stack grow? What changed from segmented to contiguous stacks?
- Q156Should you set GOMAXPROCS higher than the number of CPUs for I/O-bound workloads?
- Q157What happens to the scheduler when a goroutine makes a blocking syscall?
- Q158What is the netpoller and how does it make network I/O look blocking yet scale?
- Q159What is sysmon and what does it do?