Работали ли вы с JSON-полями или специфическими расширениями PostgreSQL
Что проверяют
Понимаете ли вы, когда схема в колонке уместна, и умеете ли работать с jsonb через ORM, не теряя записи. Вопрос практический: половина ошибок тут не в SQL, а в том, как слой Python видит изменение словаря.
Как отвечать
Сначала про типы: jsonb хранит разобранное дерево, поддерживает операторы и индексы, обычный json хранит текст и годится, только когда нужен исходный документ побайтово. Драйвер сам превращает словарь в JSON и обратно.
В SQLAlchemy берут тип JSONB из диалекта PostgreSQL, а не общий JSON, иначе операторы недоступны. Ключевая деталь, о которой стоит сказать самому: изменение словаря на месте ORM не отследит, объект не попадёт в изменённые и при flush не запишется ничего. Лечится присваиванием нового словаря либо обёрткой MutableDict.as_mutable(JSONB) на колонке.
Settings.attrs["theme"].astext == "dark"
Settings.attrs.contains({"theme": "dark"})Индекс создаётся миграцией: в Alembic это op.create_index с указанием метода GIN, а расширение включается отдельной ревизией через create extension, и на это нужны права. Из расширений называйте применявшиеся: pg_trgm под поиск по подстроке, citext, pgcrypto, pgvector под эмбеддинги.
Где спотыкаются
Мутируют словарь и удивляются, что данные не сохранились. Ошибка тихая: исключения нет, чтение внутри той же сессии проходит, потому что объект ещё в памяти, а в базе лежит старое значение.
Второе: считают jsonb поводом не иметь схемы вообще. В колонку попадает что угодно, и через год там три поколения формата, которые приходится поддерживать в коде. Валидация делается на входе моделью, а инвариант вроде «в колонке всегда объект» закрывается ограничением check.
Третье: кладут в документ деньги и время. JSON не различает целое и десятичную дробь, Decimal превращается в число с плавающей точкой и теряет копейки, а дата становится строкой произвольного формата. Таким полям место в обычных колонках с типами numeric и timestamptz.