Go arenas are gone, and that's fine

The experimental arena package is being removed in Go 1.24. Some thoughts from someone who actually tried to use it in production.

What they were

Arenas were an experimental Go package — gated behind a build tag — that let you allocate a bunch of objects together and free them in one shot, bypassing the GC for the lifetime of the arena.

The pitch was: for request-scoped allocations, you can avoid the cost of marking and sweeping objects that are obviously dead the moment the request returns. In practice, this could be a real win for services with very high allocation rates and short-lived data.

Why I tried them

A service I was running in 2024 spent about 18% of CPU in GC. The workload was almost entirely "decode a protobuf, do a thing, encode a response", and the protobufs were big. The allocations were obviously request-scoped. It looked like the textbook arena use case.

Why I stopped

Three reasons.

One: the API is viral. Once a function takes an arena, every function it calls has to either accept the arena, do nothing allocating, or use the global allocator. Refactoring even a single hot path was a project, not an afternoon.

Two: the safety story is fragile. If you free the arena and something still holds a pointer into it, you have a use-after-free. In Go. With the runtime. The safety net you expected from the language is gone, and the bug looks like spooky-action-at-a-distance.

Three: the GC kept getting better. Between the work I was doing and the time I would have spent rewriting, Go 1.21 and 1.22 made GC measurably cheaper for my workload. By the time I was ready to commit, the gap had closed enough that the risk wasn't worth it.

What I'm doing instead

Pooling. Plain old sync.Pool for the few hot allocations that matter. It's not as theoretically elegant as arenas, and it has its own foot-guns (you have to remember to Reset pooled objects), but it's been in the standard library since 1.3 and it works.

What this means

The Go team is, I think, making the right call. The arena experiment shipped, real people tried it, the tradeoffs turned out to favor "make the GC better" over "give users an escape hatch". That's how the experiment is supposed to go. Mourn briefly. Move on.

← archive