Instead of MongoDB

JSONB

Use JSONB when part of your data is still changing but the rest still wants SQL, joins, and constraints.

Usually reached for MongoDB
Postgres-first move JSONB

Start Here

JSONB is useful when only part of the row is messy.

That is common in early products. You know the user, account, owner, timestamps, and permissions. You do not yet know every setting, trait, event payload, or integration field.

Put the stable parts in normal columns. Put the moving part in JSONB.

What To Build First

Do not make the whole table a document. Keep the important columns visible.

create table profiles (
  id bigserial primary key,
  user_id bigint not null,
  created_at timestamptz not null default now(),
  traits jsonb not null default '{}'
);

create index profiles_traits_gin
  on profiles using gin (traits);

Now you can query flexible fields without losing the normal database shape.

select id, user_id
from profiles
where traits @> '{"plan":"trial"}';

Good First Uses

The key phrase is “extra attributes.” If the whole product is document-shaped, JSONB may not be the right default.

The Part People Skip

Index for real queries only.

JSONB makes it easy to store many shapes, but it also makes it easy to hide a bad model. If you start adding indexes for every key, you are rebuilding schema design the hard way.

When a field becomes important, promote it:

alter table profiles
  add column plan text;

update profiles
set plan = traits->>'plan'
where traits ? 'plan';

That is not a failure. It is the product telling you the field is now part of the core model.

What This Does Not Replace

JSONB is not a reason to avoid schema design forever. It is a way to buy time for the parts that are still unknown.

Use normal columns for fields used in permissions, billing, joins, sorting, and core filters. Those fields deserve names, types, and constraints.

Move To A Document Database When

For many apps, JSONB is enough for the flexible part while Postgres handles the system of record.

References