Build the mental model
JSONB stores parsed binary JSON and supports rich operators and indexes. Stable, required relational fields should remain real columns and relationships rather than being hidden in JSONB. JSONB suits optional evolving metadata, with structure validation supplied by the application or CHECK constraints.
Connect it to a real scenario
Add `tags` and `level` to tutorial metadata and query them with containment operator `@>`. Choose between a broad GIN index and focused expression indexes from actual queries.
Try the working example
UPDATE app.tutorials
SET metadata = jsonb_build_object(
'level', 'beginner',
'tags', jsonb_build_array('postgresql', 'database')
)
WHERE slug = 'postgresql';
CREATE INDEX tutorials_metadata_gin_idx
ON app.tutorials USING gin (metadata);
SELECT title
FROM app.tutorials
WHERE metadata @> '{"tags": ["postgresql"]}'::jsonb;You can store JSONB metadata and run an indexed containment query.5-minute try-it
Write a CHECK constraint that requires a metadata difficulty field to be one of three values.
One important caution
Putting all data into one JSONB column sacrifices foreign keys, type safety, and straightforward reporting.
PostgreSQL — JSON Types — PostgreSQL Global Development Group