Lesson 9 of 12

Tuple Deforming: Why Column Order Quietly Changes Your Row Size

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

The one thing to understand first

A row on disk is not a tidy list of named fields — it is a packed byte string with a header, an optional NULL bitmap, and then the column values laid end to end with alignment padding wedged between them. Turning that byte string back into usable column values is called deforming, and PostgreSQL does it for nearly every tuple it touches. Once you see how deforming works, two surprising facts fall out: column order can change how many bytes a row occupies, and reading a late column can cost more than reading an early one.

What a heap tuple looks like

The on-disk layout is defined by HeapTupleHeaderData in src/include/access/htup_details.h:

  • A 23-byte header (xmin, xmax, ctid, infomask flags…).
  • t_bits[] — the NULL bitmap, one bit per column, present only when the row actually contains a NULL (flagged by HEAP_HASNULL in t_infomask).
  • t_hoff — the offset where user data begins, after the header and any NULL bitmap.
  • The column values themselves, each preceded by however many alignment padding bytes its type requires.

Deforming, one attribute at a time

The work happens in heap_deform_tuple() in src/backend/access/common/heaptuple.c. It walks the tuple left to right, and for each column consults pg_attribute:

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:

  • attcacheoff: the shortcut and how it breaks
  • The practical upshot: column tetris
  • Layer 3 — Watch column order change the row size
  • 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