Lesson 11 of 12

Memory Contexts: Why PostgreSQL Almost Never Calls free()

Applies to PostgreSQL 13–17 Last reviewed Jun 2026 Grounded in source

The one thing to understand first

PostgreSQL’s C code calls palloc() thousands of times to build a query’s plan, evaluate expressions, and format results — and almost never calls the matching free. That sounds like a leak factory. It isn’t, because every allocation belongs to a memory context: a named arena that can be wiped out in one stroke. When a query ends, PostgreSQL doesn’t free a thousand objects individually — it deletes the context and every allocation inside it vanishes at once. Grasp this and a whole category of “where did my RAM go” questions becomes answerable.

palloc, and the context behind it

The interface lives in src/backend/utils/mmgr/mcxt.c. palloc(size) doesn’t take a context argument — it allocates from the global CurrentMemoryContext. Code sets that target with the standard idiom oldcontext = MemoryContextSwitchTo(ctx); ... ; MemoryContextSwitchTo(oldcontext);. Because allocation is tied to where CurrentMemoryContext points, the same palloc call can land in a short-lived per-tuple arena or a long-lived cache depending on the surrounding switch. pfree exists, but is the exception; the rule is to reset or delete the whole context later.

The allocator: aset.c

The default context type is the allocation set in src/backend/utils/mmgr/aset.c, created by AllocSetContextCreate. It grabs OS memory in blocks that grow geometrically from initBlockSize up to maxBlockSize, and carves each block into chunks for individual pallocs. Freed chunks go onto one of 11 power-of-two freelists (8, 16, 32, … up to 8 KB), so a later same-sized request is recycled without touching the OS. Allocations larger than the chunk limit (ALLOC_CHUNK_LIMIT, ~8 KB) get their own dedicated block. This design makes palloc far cheaper than raw malloc and makes bulk reset essentially free.

This is a Pro lesson

Get every Learning Pathway and cookbook recipe — grounded in PostgreSQL source code, with diagnostics, fixes, and prevention for each topic.

Continue this lesson to learn:

  • The context tree
  • The per-tuple context: the real magic
  • Layer 3 — Read your backend’s live memory tree
  • Layer 4 — The levers this hands you
  • Layer 5 — What an Oracle DBA should expect vs what they get
  • Key takeaway
  • All 36 Learning Pathway lessons
  • 170+ cookbook recipes
  • Source-grounded diagnostics & fixes

Secure checkout Cancel anytime Source-grounded

Was this helpful?

← Back to 05 — The Engine Room: How PostgreSQL Actually Executes