π§© JSONB in Production: Fast Patterns That Scale π
Why
β Flexibility of JSON with the reliability of Postgres.
β Powerful indexing & operators for speed.
Query Patterns
Do β
Index by access pattern: containment β GIN; single field β expression index.
Keep JSONB lean (no huge blobs); normalize stable keys where it helps.
Use EXPLAIN (ANALYZE, BUFFERS) to confirm index usage.
Donβt β
Donβt store everything in one giant JSONB; joins on normalized tables can be faster.
Donβt cast at runtime without a matching expression index.
Donβt forget VACUUM (ANALYZE); JSONB updates can cause churn.
Mini Checklist
βοΈ Chosen operators: @>, ?, ?|, ->, ->> fit the query?
βοΈ Indexes aligned with filters/containment?
βοΈ Verified with EXPLAIN (ANALYZE) under realistic work_mem?
#PostgreSQL #JSONB #SQL #Database #Performance #DevOps @postgres
Why
β Flexibility of JSON with the reliability of Postgres.
β Powerful indexing & operators for speed.
Query Patterns
undefined
-- Containment (has all keys/values)
SELECT id FROM products
WHERE attrs @> '{"color":"black","size":"M"}';
-- Property path filter
SELECT id FROM orders
WHERE (data ->> 'status') = 'paid';
-- Any of these tags?
SELECT id FROM articles
WHERE (tags ?| array['pg','sql','tips']);
Indexes that Matter
undefined
-- General-purpose GIN for JSONB containment / existence
CREATE INDEX idx_prod_attrs_gin ON products USING GIN (attrs);
-- Expression index for a hot field
CREATE INDEX idx_orders_status ON orders ((data ->> 'status'));
-- Partial index to target common filter
CREATE INDEX idx_paid_recent ON orders ((data ->> 'status'))
WHERE (data ->> 'status') = 'paid';
Do β
Index by access pattern: containment β GIN; single field β expression index.
Keep JSONB lean (no huge blobs); normalize stable keys where it helps.
Use EXPLAIN (ANALYZE, BUFFERS) to confirm index usage.
Donβt β
Donβt store everything in one giant JSONB; joins on normalized tables can be faster.
Donβt cast at runtime without a matching expression index.
Donβt forget VACUUM (ANALYZE); JSONB updates can cause churn.
Mini Checklist
βοΈ Chosen operators: @>, ?, ?|, ->, ->> fit the query?
βοΈ Indexes aligned with filters/containment?
βοΈ Verified with EXPLAIN (ANALYZE) under realistic work_mem?
#PostgreSQL #JSONB #SQL #Database #Performance #DevOps @postgres
β€1π₯1
π JSON vs JSONB: The Ultimate PostgreSQL Guide
Think they're the same? Think again! Here's what you're missing:
JSON: The Purist
JSONB: The Powerhouse
Performance Reality Check:
π₯ Hidden JSONB Operators:
@> Contains
<@ Contained by
? Key exists
?| Any keys exist
?& All keys exist
|| Concatenate
- Delete key/element
#- Delete at path
When to use JSON:
Logging raw API responses
Need to preserve exact format
Write-heavy, read-never workloads
When to use JSONB (99% of cases):
Any querying needed
Performance matters
Need indexing
Data aggregation
π Secret weapon:
Converted JSON to JSONB? What performance gains did you see? π
#PostgreSQL #JSON #JSONB #Database #Performance
@postgres
Think they're the same? Think again! Here's what you're missing:
JSON: The Purist
-- Stores exact text representation
-- Preserves whitespace, duplicates, order
-- Faster input (no parsing)
-- No indexing support
CREATE TABLE logs (data JSON);
JSONB: The Powerhouse
-- Binary storage, parsed on input
-- Removes duplicates, sorts keys
-- 5-10x faster queries
-- Full indexing support!
CREATE TABLE events (data JSONB);
Performance Reality Check:
-- JSONB with GIN index
CREATE INDEX idx_data ON events USING GIN (data);
-- Lightning fast queries
SELECT * FROM events
WHERE data @> '{"user_id": 123}'; -- Uses index!
-- JSON? Full table scan every time π’
π₯ Hidden JSONB Operators:
@> Contains
<@ Contained by
? Key exists
?| Any keys exist
?& All keys exist
|| Concatenate
- Delete key/element
#- Delete at path
When to use JSON:
Logging raw API responses
Need to preserve exact format
Write-heavy, read-never workloads
When to use JSONB (99% of cases):
Any querying needed
Performance matters
Need indexing
Data aggregation
π Secret weapon:
-- Partial JSONB index for massive performance
CREATE INDEX idx_active_users ON events (data->>'user_id')
WHERE data->>'status' = 'active';
Converted JSON to JSONB? What performance gains did you see? π
#PostgreSQL #JSON #JSONB #Database #Performance
@postgres
π1