# 1.1 The Tuple (The Physical Suitcase)

In the warehouse of the Lazy Elephant, a **Tuple** is the absolute smallest unit
of luggage. It’s not just a "row" of data; it’s a highly specific, slightly
neurotic physical suitcase that carries everything a record needs to survive its
journey through the database.
It is critical to distinguish between the **Logical Row** and the **Physical
Tuple**:
- **The Row (Logical)**: This is the "ghost" or the "idea" of a record. When you
say `SELECT * FROM users WHERE id=1`, you are asking for the _concept_ of that
user.
- **The Tuple (Physical)**: This is the actual physical suitcase sitting on a
conveyor belt. Because of the elephant's refusal to erase things (see
[[Postgres/Architecture/MVCC]]), a single logical **Row** might actually be
represented by dozens of physical **Tuples**—old versions, newer versions, and
deleted versions.
---
## 1. The Header (HeapTupleHeaderData)
Living in the front pocket of every suitcase is a **Bureaucratic Bird** (the
Header). This 23-byte fixed-size structure is the "passport" of the tuple. It
tells the system who created it, who deleted it, and whether it’s even legal to
look at it.
| Field | Size | Metaphor | Technical Description |
| :----------- | :------ | :------------------- | :-------------------------------------------------------------------- |
| `t_xmin` | 4 bytes | **Creation Stamp** | The Transaction ID (XID) that inserted this tuple. |
| `t_xmax` | 4 bytes | **Deletion Stamp** | The Transaction ID that deleted or locked this tuple. |
| `t_cid` | 4 bytes | **Command ID** | The specific command within the transaction that acted on it. |
| `t_ctid` | 6 bytes | **Location Tag** | The physical address (Page #, Offset) of this tuple or its successor. |
| `t_infomask` | 2 bytes | **Visibility Flags** | Bitflags describing the tuple's state (commits, aborts, has nulls). |
> [!NOTE]
> The `t_ctid` is the physical "GPS coordinate" of the suitcase. If a row is
> updated, the old tuple’s `t_ctid` is updated to point to the new physical
> location of the next version.
## 2. The Null Bitmap (The Checklist)
If your table has many columns that might be empty (NULL), the elephant doesn't
want to waste suitcase space on them. Instead, it maintains a **Checklist** (the
Null Bitmap) right after the header.
If a bit is set to 0, the elephant knows that specific "item" wasn't packed, and
it skips over it entirely when unpacking the suitcase.
## 3. The Padding Socks (Alignment)
Postgres prefers to pick up suitcases in 8-byte chunks. If your data (Header +
Bitmap + User Data) doesn't end on an 8-byte boundary, the elephant stuffs
**Useless Padding Socks** into the corners.
This is why a table with `(int, char(1), int)` might actually take up more space
than `(int, int, char(1))`. The order of your belongings matters!
## 4. TOAST (Oversized Attribute Storage)
If a single item is too big for the suitcase (usually > 2KB), the elephant won't
struggle with it. It ships the large item off to a **Separate Trailer** (the
TOAST table) and leaves a tiny "Claim Check" in the suitcase.
TOAST stands for **The Oversized-Attribute Storage Technique**, and it is the
reason you can store multi-gigabyte "life story" strings without breaking the
8KB [[Postgres/Structures/Page]] limit.