When do you actually use JSONB columns? Trying to find the line between flexibility and "this should've been relational"
Working on a new feature and genuinely torn on this one. We need to store form responses where the form structure is user-defined—different customers have different fields, field types vary, some are required, some aren't.
The JSONB approach is tempting: store the whole response as a JSON blob, index specific paths we know we'll query, call it a day. Schema changes become application-level concerns instead of database migrations.
But I've also seen JSONB become a junk drawer. One codebase I worked on had a metadata JSONB column that had accumulated 47 different keys over three years, with no documentation about what any of them meant or which ones were still being used. Querying it was an archaeology project.
Here's where I've landed so far on when JSONB makes sense:
Truly dynamic schemas where the structure is user-defined or varies significantly between records
External API responses you're caching and don't control the structure of
Sparse attributes where most records only use a few fields from a large possible set
Nested data that's always read and written together as a unit
And when it probably doesn't:
Core business entities with stable, known attributes
Data you'll frequently filter, join, or aggregate on (yes, you can index JSONB paths, but it's clunkier)
When you're using it to avoid thinking about your data model
For my current problem, I'm leaning toward a hybrid: relational tables for the form definitions and the response metadata (who submitted it, when, which form version), but JSONB for the actual answer payload since that's truly variable.
Those of you using JSONB in production—where have you found it works well versus where did you regret it? Any patterns for keeping it from becoming a maintenance nightmare?
0 Comments