<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6" -->

---
title: noalloc: Tooling and libraries to enforce zero heap...
description: Noalloc is a Go tool and library set that enforces zero heap allocations across a function's entire call tree. Mark a function with '//noalloc:root' and the...
canonical: https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: noalloc: Tooling and libraries to enforce zero heap allocations in Golang | daily.dev
og:description: Noalloc is a Go tool and library set that enforces zero heap allocations across a function's entire call tree. Mark a function with '//noalloc:root' and the...
og:url: https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6
og:image: https://api.daily.dev/og/posts/Rqog2YiX6.png
og:image:alt: noalloc: Tooling and libraries to enforce zero heap allocations in Golang
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# noalloc: Tooling and libraries to enforce zero heap allocations in Golang

**[Hacker News](https://daily.dev/sources/hn)** · 23 min read · 0 upvotes · 0 comments

## Summary

Noalloc is a Go tool and library set that enforces zero heap allocations across a function's entire call tree. Mark a function with '//noalloc:root' and the noalloc CLI reports every line that allocates, letting you fix or exempt it. It requires Go 1.27 or later and ships fixed-capacity containers (Buf, Vec, Slice, Map) plus a command, jsongen, that generates allocation-free JSON encode and decode methods. Benchmarks on an Apple M4 show jsongen decoding a 130KB feed in 1.16s with 0 allocations, versus 2.94s and 1,696 allocations for the standard library, over 3,000 operations. The repo is entirely written by AI, guided by a human, and used in production at The Consensus.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://github.com/theconsensuslabs/noalloc>

## Questions this post answers

### How can I check that a Go function and everything it calls never allocates on the heap?

Mark the function with '//noalloc:root' and run the noalloc CLI in its module; it checks the entire call tree and prints every line that allocates, such as a map write or a string concatenation that escapes to the heap. It exits 1 if it finds an allocation or 2 if it cannot run, and requires Go 1.27 or later.

_Developers trying to eliminate GC pressure in Go track tools like this one on daily.dev._

### How does noalloc's zero-allocation JSON encoder compare in speed to Go's standard encoding/json?

On an Apple M4 with Go 1.27.0, noalloc's jsongen decodes a 500-item, 130KB JSON feed in 1.16 CPU seconds with zero allocations, versus 2.94 seconds and 1,696 allocations per decode for the standard library's encoding/json. It's slower than goccy/go-json (0.74s) but allocates nothing, unlike every other library compared.

_Engineers choosing a JSON library for allocation-sensitive services can weigh benchmarks like these on daily.dev._

### What are bounded.Buf, Vec, Slice, and Map in Go and how do they avoid heap allocation?

They are fixed-capacity containers from the noalloc library: Buf is a byte buffer, Vec a list, Slice a contiguous list that can grow into larger pooled chunks, and Map holds a fixed number of entries. Each is given memory via Reset, and when a write exceeds capacity it marks itself full instead of allocating, so you check fullness once instead of after every write.

_Developers designing allocation-free data structures in Go can find patterns like this on daily.dev._

## Community take

How the wider developer community reacted, aggregated from 1 discussion and 47 comments across hackernews (as of 2026-10-29).

**TL;DR:** Discussion centers less on the tool itself and more on whether avoiding GC in Go is worth the effort at all, with many arguing that if you need zero-allocation guarantees you should just use Rust, Zig, or C++ instead; the project's author participates and clarifies implementation details.

**Sentiment:** 30% positive · 45% mixed · 25% skeptical

**The case for**

- Some find selective, opt-in allocation enforcement useful for getting close to performance budgets without a full rewrite in a systems language.
- A few see value in catching GC-induced latency spikes in soft-realtime Go services.
- Interest in the underlying approach of parsing Go compiler escape-analysis output to detect allocations.

**The pushback**

- Many argue this is over-engineering for a problem most Go applications don't actually have.
- Several suggest that if you truly need zero allocations, you should use Rust, Zig, or C++ instead of fighting Go's design.
- Relying on undocumented/non-standard compiler escape-analysis output (`-gcflags=-m -S`) is seen as fragile across Go versions.
- Some feel Go's design (goroutines, closures, GC) is fundamentally mismatched with embedded/real-time/high-frequency use cases this tool targets.

**By community**

- hackernews (mixed): Debate splits between people who find opt-in allocation-free tooling genuinely useful for latency-sensitive Go services and those who think it's a workaround for choosing the wrong language in the first place.

**Hottest debate:** Whether it's worth contorting Go to avoid GC at all, versus simply using a systems language like Rust or C++ when zero allocations matter.

**Open questions**

- Will Go's compiler escape-analysis output remain stable enough across versions for this tool to rely on?
- Could allocation-free enforcement eventually be built directly into the Go compiler/language instead of as external tooling?

**Highlights**

> Hey folks, this is my project. I really liked OxCaml's zero_alloc feature [0], something you don't get in Rust or Zig or Go*, and have been trying to get a handle on allocations in The Consensus's code search engine. It's an extremely early project but it's been helping me out a bunch already. Would love to hear your bug reports or requests if you try running it on your codebase. [0] https://theconsensus.dev/p/2026/06/27/the-feature-in-oxcaml-... * I think you can get this in Clang and maybe GCC with `__attribute__((nonallocating))` though.
> — [eatonphil on hackernews · 1 comments](https://news.ycombinator.com/item?id=50294088)

> Goroutines and lexical closures create a dilemma for embedded targets. Go was designed around the notion that using goroutines (threading, basically) should be effortless and employed without hesititation. Lexical closures is a critical aspect of that, and by extension GC. Both goroutines and lexical closures require dynamic allocation, at least when combined with some other Go design decisions (e.g. seamless recursion, dynamic method invocation, etc). Go does a great job of making these impose minimal cost, both technically and cognitively, on typical platforms, from server (including many "embedded" server environments) to desktop to smartphone. That's why it has such a sophisticated yet largely transparent user space threading layer. But it's very difficult and usually impractical for Go to target extremely resource constrained environments without exposing and crippling it's core abstractions. Some people are willing to contort Go to fit that space, but perhaps that's because their vision of what makes Go, Go, differs from the creators' and core maintainers' understanding of Go.
> — [wahern on hackernews](https://news.ycombinator.com/item?id=50294450)

> The end state of inappropriate use of garbage collected languages. Go/GC are mostly fine for medium frequency medium scale mid stack problems. It’s bad for high frequency computing. It’s bad for very small targets, for very large targets, and by association software that lives at the very bottom of the stack. Go is a high efficiency framework for writing mid sized servers, not a systems language. The runtimes hard opinions and closed interface are the reason for this enclosing definition and the GC is one part of that.
> — [raggi on hackernews](https://news.ycombinator.com/item?id=50294066)

> If you don't allocate, why do you even need Go or Rust? LLMs handle less elegant syntax just as well. I use a zero-malloc C dialect with slices and bounds-checking. Just recently I was sketching a smallish database in zero-malloc C. https://replicated.live/blog/db That was partly because most LSM data structures are read-only, so mmap was good enough and concurrent access was safe for the bulk of the data. The "hot zone" (memtable) then requires some intricate engineering, but that is the case either way. You can go quite far with zero-malloc C.
> — [gritzko on hackernews · 1 comments](https://news.ycombinator.com/item?id=50294165)

> I think that people hyperoptimize for no reason though. How many applications are there that require no GC? I feel like you can write the no-gc code in Rust and then just use it from the C ABI from any GC language.
> — [vatsachak on hackernews · 5 comments](https://news.ycombinator.com/item?id=50293220)

**Source threads**

- [hackernews](https://news.ycombinator.com/item?id=50278645) · 64 points · 47 comments

## Similar posts on daily.dev

- [Internals for Interns](https://daily.dev/posts/internals-for-interns-fg0xibngw) · Hacker News · 0 upvotes · 0 comments
- [Allocating on the Stack](https://daily.dev/posts/allocating-on-the-stack-9ni5vn4pu) · Go · 62 upvotes · 0 comments
- [Issue \#611: Go can't kill a stuck goroutine — Go Weekly](https://daily.dev/posts/issue-611-go-can-t-kill-a-stuck-goroutine-go-weekly-q2lj7rsf3) · Golang Weekly · 5 upvotes · 0 comments

---

Tags: [#general-programming](https://daily.dev/tags/general-programming), [#golang](https://daily.dev/tags/golang)

[View this post on daily.dev](https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"noalloc: Tooling and libraries to enforce zero heap allocations in Golang","url":"https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6"},"datePublished":"2026-10-29T19:57:18.206Z","dateModified":"2026-10-29T23:50:59.239Z","description":"Noalloc is a Go tool and library set that enforces zero heap allocations across a function's entire call tree. Mark a function with '//noalloc:root' and the...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/51f9cd3dd77abcc1d5eeaab4a4e49245?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/51f9cd3dd77abcc1d5eeaab4a4e49245?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Hacker News","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hacker News","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/hn","url":"https://daily.dev/sources/hn"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"general-programming,golang","timeRequired":"PT23M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hacker News","item":"https://daily.dev/sources/hn"},{"@type":"ListItem","position":3,"name":"noalloc: Tooling and libraries to enforce zero heap allocations in Golang"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/noalloc-tooling-and-libraries-to-enforce-zero-heap-allocations-in-golang-rqog2yix6#faq","mainEntity":[{"@type":"Question","name":"How can I check that a Go function and everything it calls never allocates on the heap?","acceptedAnswer":{"@type":"Answer","text":"Mark the function with '//noalloc:root' and run the noalloc CLI in its module; it checks the entire call tree and prints every line that allocates, such as a map write or a string concatenation that escapes to the heap. It exits 1 if it finds an allocation or 2 if it cannot run, and requires Go 1.27 or later. Developers trying to eliminate GC pressure in Go track tools like this one on daily.dev."}},{"@type":"Question","name":"How does noalloc's zero-allocation JSON encoder compare in speed to Go's standard encoding/json?","acceptedAnswer":{"@type":"Answer","text":"On an Apple M4 with Go 1.27.0, noalloc's jsongen decodes a 500-item, 130KB JSON feed in 1.16 CPU seconds with zero allocations, versus 2.94 seconds and 1,696 allocations per decode for the standard library's encoding/json. It's slower than goccy/go-json (0.74s) but allocates nothing, unlike every other library compared. Engineers choosing a JSON library for allocation-sensitive services can weigh benchmarks like these on daily.dev."}},{"@type":"Question","name":"What are bounded.Buf, Vec, Slice, and Map in Go and how do they avoid heap allocation?","acceptedAnswer":{"@type":"Answer","text":"They are fixed-capacity containers from the noalloc library: Buf is a byte buffer, Vec a list, Slice a contiguous list that can grow into larger pooled chunks, and Map holds a fixed number of entries. Each is given memory via Reset, and when a write exceeds capacity it marks itself full instead of allocating, so you check fullness once instead of after every write. Developers designing allocation-free data structures in Go can find patterns like this on daily.dev."}}]}
```

