Should I choose NoSQL or PostgreSQL for flexible product attributes?
Question
On a new project we'll design a flexible product attribute system (color, size, warranty period, etc. — different for every product). In a relational DB the EAV model brings complex SQL and performance loss; NoSQL (MongoDB) looks attractive with its schemaless structure. Given the ACID requirement, data consistency, and reporting needs, by what parameters should I choose between these two worlds?
Answer
Short answer: don’t reach for MongoDB just because attributes vary from product to product — that’s exactly the NoSQL trap. PostgreSQL’s JSONB gives you a third, more accurate option.
Short answer
The pain is real: EAV (entity-attribute-value) in a relational DB genuinely hurts — huge joins, unreadable SQL, performance loss. But that pain shouldn’t push you straight into schemalessness. I’ve discussed the architectural sibling of this reflex — the urge to start a new project directly on microservices — in a separate answer; the decision procedure is the same here.
Why
- Your reporting need alone decides it. You say you need heavy reporting. If you split data into Mongo you can’t run those reports as a single SQL query against your PostgreSQL data, and you’re stuck stitching data from two systems. That single requirement is enough to argue against splitting.
- Products, prices and orders are the spine of your business. Everything where you want ACID, joins and reporting lives here; you don’t want to give up transactional guarantees, foreign keys and
JOIN-based reports. - The scenario where document NoSQL is right isn’t yours. Moving to MongoDB makes sense only when all access is key-based, you don’t need cross-entity transactions/reporting, and the entire domain is genuinely document-shaped.
What to do
- Keep the relational core in PostgreSQL. Products, prices, orders, stock — everything where you want ACID, joins, and reporting stays relational.
- Put the variable attributes in a single
JSONBcolumn. Hold the fields that vary per product — color/size/warranty — in oneJSONBcolumn. - Add a GIN index on that
JSONBcolumn. Queries likeattributes @> '{"color":"red"}'then run fast. You get schema flexibility where you need it and transactional integrity everywhere else.
Bottom line: PostgreSQL + JSONB (GIN-indexed) for the variant attributes. Consider NoSQL only if the access pattern truly demands it. Starting with “it has no schema, this’ll be easy” makes you pay a much heavier consistency-and-reporting bill later — I unpack why this architectural choice is a trap in the sade.dev piece.
Related Reading
Comments
Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.