PostgreSQL Tip: How to Use JSONB (Without Treating It Like MongoDB)
Most engineers misuse JSONB here’s how to avoid the trap.
Most engineers hear PostgreSQL supports JSONB and assume it behaves like a document database.
It doesn’t and understanding this difference is the key to using JSONB correctly and avoiding performance traps.
PostgreSQL is a relational engine with JSON flexibility, not a MongoDB replacement.
This matters for performance, indexing, and how you design your schema.
When you SHOULD use JSONB
JSONB is perfect when:
• You store semi-structured data (metadata, user settings, event payloads)
• The schema is stable, but some fields are optional
• You only query a few JSON keys regularly
• You want SQL + NoSQL flexibility in one place
• You need light document flexibility inside a relational model
This is exactly what JSONB was built for.
When you SHOULD NOT use JSONB
Avoid JSONB for:
• Heavy document-style workloads
• Frequent updates on large nested JSON structures
• Deeply unstructured data with unpredictable fields
• Use cases that expect MongoDB-level document performance
If you’re designing a full document store, PostgreSQL is not that tool and JSONB is not MongoDB.
Don’t panic! [15+ SQL Queries] New Post is LIVE ➡️
💡 The Checklist Mindset Playbook for Managing Sev-1 Cases
This includes:
A proven incident-handling mental model
How to think clearly under pressure
How to avoid panic debugging
25+ practical SQL queries.
Price 39$
If you manage production systems, this playbook will change how you operate.
After resolving 950+ Sev-1 incidents for Fortune 100 customers at Microsoft, I rely on one checklist mindset that never fails and you can get it from here.
I documented it here → [Playbook link]
🚀 Discover the new PostgreSQL Health Report one SQL file to diagnose Sev-1 incidents in minutes and fix them fast!
Price 29$ with 60+ SQL Queries + Actionable Fix Commands
Querying JSONB (Simple Example)
SELECT data->>'name' AS customer_name
FROM customers
WHERE data->>'status' = 'active';
This is great for extracting 1–2 fields inside event logs, audit data, or metadata columns.
Indexing JSONB (Most Important Part Engineers Miss)
If you filter or sort by a specific JSONB indexing, use a B-tree expression index:
CREATE INDEX idx_customer_status
ON customers ((data->>'status'));
Why this is better than GIN for key-specific queries:
• Smaller and lighter
• Faster to probe
• Cheaper to maintain
• Ideal when you only need 1–3 keys
Use GIN only when you need full-document search across many keys.
FAQ
1. Should I store entire documents in JSONB or keep most columns in relational tables?
Short answer: Keep core, predictable fields relational. Put only optional, variable, or rarely queried fields in JSONB.
Many teams dump entire documents into JSONB because it feels flexible.
But when you need to filter, index, or join on these values later, performance drops fast especially with wide JSONB objects.
The winning pattern:
Use relational columns for the data you query often
Use JSONB only for metadata or fields that change often
Avoid stuffing everything into JSONB just because it’s easy
This balances performance and flexibility without locking you into a document-database mindset.
2. Can JSONB replace MongoDB for real document workloads?
Short answer: No, not for high-volume document-style workloads.
PostgreSQL JSONB is fantastic, but it’s not meant to be a full document engine.
If you need:
deeply nested documents
high write rates
rapid schema changes
heavy partial document updates
document versioning
MongoDB (or another document DB) will handle those patterns better.
JSONB shines when:
80% of your model is structured
20% is flexible
you need SQL + some NoSQL features
you want everything in one database
your queries hit only a few JSON keys
If your entire application behaves like a document store, MongoDB will outscale JSONB sooner or later.
Key Takeaway
JSONB is one of PostgreSQL’s most powerful features but only when used correctly.
Treat it as structured-relational data with optional flexibility, not a full NoSQL document engine.
Get this right, and you’ll avoid bloat, reduce index overhead, and dramatically improve PostgreSQL performance.
💡Paid members get instant access to:
Premium content with Deep dive into full RCA analysis, get actionable scripts, and Ask Me Anything via Email for Mentorship.
👉 Share, Restack, or Recommend this post to help others learn.
Thanks again for reading
See you in the next post! 🚀



Nice explanation. I totally agree with that fact that we should not use Postgres as Document DB just based on JSONB. If you need extreme read or write scale on documents or your access patterns are more likely document-oriented then never use it as document db.
But there are some libraries like Marten which uses Postgres as document db (mainly because of JSONB), which is mainly used in Event Sourcing patterns. And it is one of the best library to use for this kind of scenario.
So overall it depends upon your use case.
Phenomenal articulation of a nuance that trips up so many engineers moving between database paradigms.
The btree expression index guidance is particularly valuable. I've seen teams default to GIN indexes on JSONB columns because it feels like the "proper" NoSQL approach, then wonder why their query performance degrades as data scales. The reality is that if you're consistently filtering on the same 1-3 keys, that btree index on the extracted value gives you exactly the performance characteristics you'd get from a regular relational column, without the schema rigidity.
One thing worth emphasizing: the 80/20 model you describe (80% structured, 20% flexible) is aspot-on heuristic for when JSONB makes sense. The danger zone is when teams use JSONB as an escape hatch for poor schema planning. I've debugged systems where critical business logic was buried in JSONB fields precisely because the team wanted to avoid migrations, and the maintenance cost compounds fast when you need to refactor queries across thousands of variable-structure JSON blobs.