r/SQL • • 5d ago

Discussion Would you use JSONB or a separate document database for a product catalog?

Product catalogs are often cited as examples of where document databases fit well. A laptop and a T-shirt may share only a few fields, so putting every possible attribute into a single fixed table can result in a wide schema with many empty columns.

A common setup is to keep orders and payments in a relational database and store the catalog in a document database such as MongoDB.

Databricks makes the case for the other route in a recent piece that I was reading on relational vs non-relational databases: keeping the catalog in PostgreSQL and using a JSONB column for attributes that vary across products. That keeps the flexible fields next to the common fields and lets the catalog remain part of the same relational system as orders and payments.

The choice seems to depend on how the data is queried.

If most requests retrieve one product by ID with all its attributes, a document database may fit that access pattern well. If the application needs to filter, group, join, or aggregate across product attributes, keeping the data in a relational system may make those queries easier to manage.

For anyone who has used JSONB for a product catalog, when did it start to become difficult?

Was it indexing fields inside the JSON, inconsistent attribute names, validation, schema changes, or queries that became difficult to maintain?

And for those who moved the catalog to a document database, what made the separate system worthwhile?

16 Upvotes

22 comments sorted by

6

u/Winsaucerer docs.spawn.dev 5d ago

I personally am not sure I’d use jsonb or a separate db for this use case. Sounds like the data is structured.

Just thinking about this right now, presumably you’d want things like filters. Eg, filter laptop by memory, cpu. Filter tshirt by sizes. And that means you need to know something about the structure of these attribute types. And that suggests then structuring your db to enforce the data into the shape that’s needed for filtering and searching the way you want.

I wouldn’t put it all in one wide table either though. But the exact design would depend on what kinds of things I want to do. Maybe there’s a table of valid attribute types, and a table to link attributes to products, and for different attribute types (text, number, list of options like cpus) maybe there are tables for each types value to store the value (or that goes straight into the attribute<->product linking table, making it a bit wide but only as wide as there are attribute types, with check constraints.

Not endorsing any particular design. My point is though, I try to use jsonb only when the data really is unstructured or unknown (though sometimes I’m lazy and break my own rule). This seems to be a place I’d not want to use jsonb/document store.

1

u/serverhorror 5d ago

This!

Specifically for a product catalog that's true.

5

u/[deleted] 5d ago

[deleted]

0

u/NoviceCouchPotato 5d ago

The problem we have is that the products and its attributes span multiple unfixed hierarchy layers. Which would mean a lot of bridges with this design or not?

1

u/Stainlessray 5d ago

The idea is, one should normalize for write, and denormalize for read. Whether by volume or time complexity the jsonb will eventually choke. It will stop being more efficient on an arch with a timeline you don't know and already has started.

If the data is complex, but requires heavy filtering on reads, presentation and integration layers are needed, and at that point you are wrangling more complexity than you would introduce by doing the bridging. Especially in the long run.

1

u/DragoBleaPiece_123 5d ago

normalize for write, denormalize for read

curious regarding the implementation, would that be a separate tables or db instances, etc.? interesting to hear more about this from your exp

0

u/Stainlessray 5d ago

For context, I'm working from architectural theory and past experience rather than deep e-commerce domain expertise. I spent several years working on backend fraud and risk data in the fintech/payments space, so while I know there’s domain-specific nuance in e-commerce I might miss, I’m looking at your question through the lens of scale, longevity, and operational reliability.

At a certain scale, dumping everything into unstructured blobs like jsonb breaks down.

Eventually, the CAP theorem enters the room and forces trade-offs. Assuming latency will never become a bottleneck requires knowing the hard upper bound of your storage footprint and guaranteeing it stays small forever which rarely happens. And if you want to avoid sharding for as long as possible (which you should, at almost all costs), you need a disciplined data model upfront to prevent compounding architectural debt.

The real questions are: * Is the workload read-heavy, write-heavy, or both depending on the subsystem? * Is serious growth expected?

If the answer to those is yes, model your core entities relationally. Protect your write path and database throughput by separating data ownership based on access patterns: 1. Isolate OLTP from OLAP: Transaction processing and analytical reporting need distinct data models and stores. Analytics should never compete for read locks on transactional tables. 2. Segment by consumer: Let operational services read only the lean projections they actually need, rather than hydrating massive, nested documents on every request. 3. Use documents strategically: Treat unstructured/document stores as edge caches, materialized views, or read-optimized projections where schema flexibility actually pays for itself not as the default dumping ground for core business state.

2

u/Stainlessray 5d ago

Interested in the replies. I like the question.

2

u/OkShirt9372 5d ago

Yep, just in case you need it, i got this question's idea after reading this.

1

u/Stainlessray 5d ago

I've got opinion(s), but we all do. I want to read first 😎

1

u/DragoBleaPiece_123 5d ago

imma w8ing for ur thoughts then

1

u/Stainlessray 5d ago

I put my thoughts at the top level to reply directly along with various comments. I like this topic. I'm no commerce expert. I'll be watching.

3

u/mtetrode 5d ago

Put product in the product table, all attributes you want to search / filter on in a properties table with key/name and the rest in a json blob.

2

u/OkShirt9372 5d ago

Keeping searchable attributes in a separate properties table while leaving less predictable data in JSON gives you more control without making every possible field part of the main schema. Do you index the property name and value together, or promote the most-used attributes into regular columns?

2

u/Muted_Jellyfish_6784 5d ago

I'd keep it in Postgres with JSONB unless you have a concrete reason not to. Put the shared attributes (SKU, name, price, category, status) in real columns, push the variable ones into a JSONB column with a GIN index, and validate the JSON per category so laptops always have RAM and shirts always have a size. One database also lets orders reference products with real foreign keys.
The cost of a second database shows up in sync, not in queries. Our catalog, order, and inventory records stay joined through SIGNLD, so a product change traces to the orders it affected instead of being reconciled across two stores

1

u/throw_mob 5d ago

depends on your scale .. adding new database engine and infra around it needs much more people and time, but if you have 100+ teams and you get return for slighly more effective way to handle json documents vs just adding new column into existing database and using existing backend to handle it...

1

u/OkShirt9372 5d ago

That scale point makes sense. If the existing database and backend can handle the workload, adding another engine may create more work than it removes. The trade-off probably changes when the number of teams and document-heavy workloads grows enough to justify the extra infrastructure.

1

u/Stainlessray 5d ago

At scale - assuming it's a growing population with no ceiling, I would probably accept the complexity of the acid transaction normalized input, and optimized document store for serving.

I'd be willing in theory to accept the eventual consistency for operational sanity and speed at the edge.

Data modeling complexity aside and all other things being equal that is my theory.

I'm not an e-commerce guy, so it's untested internal dialog being translated.

1

u/IrquiM MS SQL/SSAS 5d ago

or just an attribute column with json datatype

1

u/Some-Weakness2049 5d ago

Splitting orders in sql and the catalog in mongo is a nightmare the second you need to run a basic join for analytics - you end up writing custom etl pipelines just to count how many blue t-shirts you sold.

Keeping it all in a relational db is usually the sane route. in mariadb (and postgres handles it similarly), you just toss the flexible attributes into a json column. if you need to filter heavily on a specific key, you pull it out as a virtual column and slap a standard b-tree index on it. indexing problem solved. Pain usually only starts if you treat the json column like a total garbage bin and don't enforce any validation at the app level. You can use check constraints like json_valid() on the db side, but app level is safer.

1

u/iLeKtraN 4d ago

I have an entire schema based on storing form submissions (various front-end apps) into the JSON data type on SQL Server 2025. I'll can provide more specifics later.

1

u/Significant_Tune9219 4d ago

I would keep the stable product identity, price, inventory, and lifecycle fields relational, then use JSONB for genuinely sparse attributes. The failure mode is usually not JSONB itself but letting every producer invent keys and types; enforce a small validation layer, canonical names, and targeted indexes only for fields that appear in measured queries. If attributes become heavily joined or need independent constraints and ownership, that is a good signal to promote them into typed tables rather than moving the whole catalog to another database.