Nockchain asks a fairly brutal thing of the runtime: keep a huge, evolving Noun graph alive; mutate it through Nock evaluation; persist the accepted state; and come back after restart without replaying the universe from scratch. The Persistent Memory Arena, or PMA, is the piece that makes that shape of system practical.

At a high level, the PMA is a file-backed arena for long-lived Nouns. The VM still uses the `NockStack` as fast ephemeral workspace while evaluating events. When state needs to survive beyond that stack frame, the changed part of the noun graph is copied into the PMA and represented as offsets into a persistent slab.
That sounds like plumbing. It is not just plumbing. It is the difference between “the node has to rebuild giant state from logs/checkpoints” and “the node can mmap durable state, validate the event boundary, and keep going.”
The short version
The PMA gives us:
- Fast allocation for persistent state: updating any arbitrary subset of the persistent subject is a bump allocation in the persistent memory arena slab, not a general-purpose allocator call.
- Fast and perfect garbage collection: GC takes ~5-10 seconds on a well-provisioned machine with fast NVMe SSD storage. It's a copy-compaction GC akin to the (now ephemeral) NockStack's garbage collection design.
- Structural sharing: unchanged subtrees already in the PMA are reused instead of copied again. Structural sharing survives garbage collection without compromising GC efficiency through careful in-place forwarding pointer rewrites during GC.
- Position-independent persistence: PMA nouns are stored as offsets, so the file can be mapped at a different address after system restart.
- Fast boot paths: a valid PMA plus sidecar metadata can boot at the SQLite event boundary without full replay. Happy-path boot now takes seconds instead of minutes.
- Fast and comprehensive durability and integrity: the PMA's meta sidecar is the last thing to get fsync'd during a durability event. The `.meta` sidecar includes the current event id. If the NockApp boots and the current PMA slab's event id doesn't match the highest event id of the `sqlite3` event log, it falls back to the snapshots which includes more intensive integrity checks including blake3 hashing and replays the event log against the snapshot booted. There are always three snapshots: latest, latest - 1, and epoch (PMA start). It can fall back to the next snapshot if an integrity check fails.
- Better peak-memory behavior: durable state lives in a file-backed mapping instead of forcing every workflow through one giant transient heap object.
- Faster transaction throughput: Pokes (effectful events that can change the persistent state) are now much faster, especially the smaller/faster pokes. Moving the Arvo (persistent subject) out of the NockStack means that it's no longer compacting event leftovers over the entire Arvo. This shaved 600-800 milliseconds off of event execution. The default and rather paranoid `fsync`/`fdatasync` configuration only adds ~2-4 milliseconds back. This dropped the time required to execute events like the timer event (does almost nothing) by over 100x.
- Safe growth: the growable PMA can extend capacity without moving already-mapped PMA data and without retrying a half-mutated noun copy. It picks right back where it left off mid-copy in-place with no corruption or moved pointers. We rely on `MAP_FIXED` in order to keep pointers stable mid-copy to the PMA in the cases where we need to grow the PMA during post-event persistence. This is standard POSIX functionality and keeps the Nock runtime functional for both Linux and macOS users.
- PMA slabs are sized and grown according to need: Unlike the NockStack, PMA is not fixed size during runtime. Because we recently added safe growth to the PMA since PMA's initial release, the PMA slabs are now just the size of the live-set + trailer + spare capacity instead of being a fixed 16 GiB slab. This saves both disk space and disk write-through burden for SSDs. PMA was already better than the original implementation's checkpointing in terms of write-through burden but this makes it even better.

Here's a screenshot of a baseline (pre-PMA) peer running at roughly the same block height as a post-PMA peer, this is a zoomed-in htop screenshot of the RSS:

The baseline peer was oscillating between 34 and 68 GiB of RSS utilized. The PMA was using ~1.8 GiB of RSS and was much more stable.
Why this is hard

A Noun is either a direct atom, an indirect atom, or a cell. Direct atoms fit in one word. Indirect atoms and cells point at allocated memory. That is convenient while the VM is running, but raw process pointers are poison for durable storage: after restart, the operating system is free to map the file at a different base address.
The PMA solves this by splitting the world into two spaces:
1. The stack: ephemeral workspace used by the interpreter.
2. The PMA: persistent, file-backed storage for long-lived noun data.
When a noun is copied into PMA, allocated substructures are rewritten into offset form. The offset is relative to the PMA base, not the process’s current virtual address. On the next boot, the runtime maps the file, gets whatever base address the OS gives it, and reconstructs pointers as `base + offset`.
That one design choice is doing a lot of work. It gives us normal pointer-speed access while the process is alive, but it also gives us a representation that survives process death.
The important trick: append only what changed
The PMA is bump allocated. Allocation advances `alloc_offset`; there is no free list on the hot path.
That is intentionally boring. Bump allocation is about as cheap as allocation gets: compute the next offset, check capacity, return the old pointer.
The more interesting part is what gets allocated. If a noun is already in PMA, it does not need to be copied again. If a new event only changes the outer spine of a tree, only that changed spine is appended. Unchanged subtrees keep pointing at the old PMA offsets.
What this buys during boot and recovery
The PMA is not the only source of truth. The SQLite event log remains the accepted-event authority. The PMA is a durable, mmap-able state image that is safe to use when its metadata matches the event-log boundary.
The recovery hierarchy is roughly:
1. If the active PMA is valid and its sidecar event number matches SQLite max, use it.
2. Otherwise, try verified snapshots.
3. Otherwise, try checkpoints that can replay to the SQLite boundary.
4. Otherwise, replay from fresh state if the event log is continuous.
That hierarchy matters because it lets the node take the fast path when the PMA is valid, while still refusing to silently discard newer event history. A PMA that is ahead, behind, invalid, or missing does not get blindly trusted.
This is the kind of reliability work that does not look flashy until it saves you from a bad deploy or a dirty shutdown.
The Accomplishment
The PMA is one of those pieces of infrastructure that sounds inevitable after it exists. It was not inevitable.
It required lining up several low-level invariants at once:
- Noun tag bits have to distinguish direct atoms, indirect atoms, cells, forwarding pointers, and PMA offsets correctly.
- Offset-form nouns have to be readable after restart even when the mmap base changes.
- Copying has to preserve sharing without duplicating giant subgraphs.
- Persistence has to write PMA data, trailer metadata, and sidecar metadata in an order that recovery can reason about.
- Growth has to happen without moving existing mappings.
- Legacy fixed-size PMAs have to remain openable by new binaries.
- Operators need enough metadata to know whether a node is healthy, nearly full, growing, stale, or recovering.
That is a real systems accomplishment. It is not a benchmark trick and it is not a cosmetic optimization. It is a durable-state architecture for a VM whose native data model is a pointer-rich graph of nouns.
What comes next
The PMA gives us the foundation for more work that would be much harder without it:
- cleaner separation between ephemeral stack sizing and persistent PMA sizing;
- better compaction policies for old unreachable PMA data;
- richer dashboards around capacity, growth, snapshots, and event-boundary health;
- direct-to-PMA bootstrap paths for very large state loads;
- more snapshot formats that copy used state instead of reserved capacity.
But the core is already the important thing: Nockchain has a persistent arena that matches the shape of its data. It can keep long-lived noun state in offset-addressed mmap storage, share unchanged subgraphs, grow safely, and recover through explicit metadata instead of hope.
That is why the PMA is such a big deal.