Do Go maps shrink after you delete entries? How do you reclaim the memory?
Question 360HardGo 1.22 to 1.25
No. delete and clear(m) free the slots for reuse, but the map's bucket and table storage never shrinks. If a map briefly held 10 million entries, it keeps that memory until the whole map becomes unreachable. This is true for the classic bucket map and for the Swiss-table implementation that became the default in Go 1.24. Swiss tables use less memory per entry and look up faster, but they still do not shrink.
// Reclaim by rebuilding: allocate a right-sized map and copy live entries.
func compact[K comparable, V any](m map[K]V) map[K]V {
out := make(map[K]V, len(m))
for k, v := range m {
out[k] = v
}
return out
}
// usage, inside a function; the old map becomes garbage:
// sessions = compact(sessions)
Gotcha: maps.Clone is not a way to shrink. It may copy the internal structure at its current size. Use a fresh make with a size hint and copy into it.
Related tips:
- Large values:
map[K]*Vlets the element memory be freed even though the table stays. Largemap[K]Vvalues are stored inline, or indirectly if bigger than 128 bytes. - Maps with no pointers in their keys or values, like
map[int]int, are not scanned internally by the GC. That makes them much cheaper for large caches thanmap[string]*T. - For long-lived caches with churn, use size limits and eviction, or shard and periodically rebuild.
More on Memory, GC & Runtime Internals
- Q358What does this print, and what memory problem does it illustrate?
- Q359Why can removing elements from a slice of pointers leak memory?
- Q361How do goroutine leaks happen, and how do you detect them?
- Q362Is
time.Afterin a loop a memory leak? What changed in Go 1.23? - Q363How do you find a memory leak in production with pprof?
- Q364How does GOMAXPROCS interact with containers, and how does it affect GC?