Ever wondered what PostgreSQL does when one column contains a really large value?
Let's say we have a meta_assets table:
CREATE TABLE meta_assets ( id BIGSERIAL, name TEXT, metadata JSONB );
Now imagine metadata contains a very large JSON document.
Your application still sees one simple row:
meta_assets
id name metadata
1 Creative A { ...large JSON... }
But PostgreSQL stores table data in pages, typically 8 KB in size. A very large value may not fit comfortably inside the row.
This is where TOAST comes in.
TOAST stands for The Oversized-Attribute Storage Technique.
PostgreSQL can compress a large value. If it is still too large, it can move the value out-of-line into a separate TOAST table.
Large metadata value
|
↓
Try compression
|
┌───┴───┐
↓ ↓
Small Still large
↓ ↓
Compressed TOAST storage
value ↓
split into
chunks
Those chunks are managed by PostgreSQL. You don't need to create or manage the TOAST table yourself.
Now let's see what happens when your application actually asks for that large value.
SELECT metadata FROM meta_assets WHERE id = 1;
Application
|
| SELECT metadata
↓
PostgreSQL
|
↓
Find row in meta_assets
|
↓
Find TOAST reference
|
↓
Read TOAST chunks
|
├── chunk 1
├── chunk 2
├── chunk 3
└── chunk 4
|
↓
Reconstruct large value
|
↓
Return metadata
|
↓
Application receives:
{
"campaign": "...",
"creative": "...",
"metadata": "..."
}
The application doesn't see the chunks. It doesn't see the TOAST table. It doesn't even need to know TOAST exists.
PostgreSQL handles the whole process and returns the value as a normal JSONB, TEXT, or BYTEA value.
That's the clever part.
What looks like one large value to your application might actually be compression, a TOAST reference, and multiple chunks underneath.
And the reverse happens when you read it: PostgreSQL follows the reference, collects the chunks, reconstructs the value, and sends the result back to you.
You write one simple SELECT.
PostgreSQL handles the storage complexity underneath.
That's TOAST.
Simple on the surface. Pretty clever underneath.