JSON Vs JSONB Storage
Summary: json stores an exact text copy of the input; jsonb stores a
parsed binary structure — that one difference explains their speed, indexing,
and operator support trade-offs.
At a glance​
| Question | Answer |
|---|---|
| What is it? | Two PostgreSQL types for storing JSON data |
| Why does it matter? | They differ in storage format, which changes speed, indexing, and which operators work |
| When do I use it? | Almost always jsonb, unless exact input formatting must be preserved |
How it works​
json | jsonb | |
|---|---|---|
| Storage | Exact text copy of input | Parsed, decomposed binary format |
| Whitespace/key order | Preserved exactly | Not preserved |
| Duplicate keys | All stored (last wins on read) | Only last duplicate kept |
| Write speed | Faster (no parsing) | Slightly slower (parses on insert) |
| Read/query speed | Slower (reparses every query) | Faster (already parsed) |
| GIN indexing | Not supported | Supported (@>, ?, etc.) |
Operators (||, jsonb_set, etc.) | Not supported | Supported |
Example​
-- clarify_history column is jsonb, which is why || and jsonb_set work on it
alter table patch_sessions add column clarify_history jsonb;
If that column were json instead, the \|\| concatenation would not work at
all — json has no \|\| operator.
Remember​
- Default to
jsonbfor nearly all use cases. - Use
jsononly when exact byte-for-byte input (whitespace, key order, duplicate keys) must be preserved — rare, mostly audit-logging scenarios. - Operators like
\|\|and functions likejsonb_setonly exist forjsonb.
Related notes​
- PostgreSQL JSONB Merge Tools - operators that only work because the column is
jsonb