Коротка відповідь. Питання «SQL чи NoSQL» на співбесіді перевіряє не знання назв, а вміння міркувати від даних: які зв'язки між сутностями, наскільки важлива консистентність, як читається і пишеться інформація. Сильна відповідь завжди починається з «залежить від задачі» і продовжується конкретними критеріями. Слабка – з «NoSQL швидший». Нижче – один приклад у двох моделях і готова рамка аргументації.

Одна задача – дві моделі

Візьмемо магазин: користувачі, товари, замовлення. Замовлення містить кілька товарів із кількістю.

Реляційна модель (PostgreSQL)

Дані нормалізовані: кожна сутність у своїй таблиці, зв'язки через зовнішні ключі:

CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL UNIQUE
);

CREATE TABLE products (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  title TEXT NOT NULL,
  price_cents INTEGER NOT NULL CHECK (price_cents >= 0)
);

CREATE TABLE orders (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE order_items (
  order_id UUID NOT NULL REFERENCES orders(id),
  product_id UUID NOT NULL REFERENCES products(id),
  quantity INTEGER NOT NULL CHECK (quantity > 0),
  PRIMARY KEY (order_id, product_id)
);

«Усі замовлення користувача з товарами» – це JOIN:

SELECT o.id, o.created_at, p.title, oi.quantity
FROM orders o
JOIN order_items oi ON oi.order_id = o.id
JOIN products p ON p.id = oi.product_id
WHERE o.user_id = $1
ORDER BY o.created_at DESC;

Що дає модель: база сама гарантує цілісність (не можна створити замовлення неіснуючого користувача), а нові способи читання даних не вимагають зміни схеми.

Документна модель (MongoDB)

Замовлення – один документ, у який вкладено товари:

// Колекція orders
{
  _id: ObjectId('...'),
  userId: ObjectId('...'),
  createdAt: ISODate('2026-09-24T10:00:00Z'),
  items: [
    { productId: ObjectId('...'), title: 'Клавіатура', priceCents: 250000, quantity: 1 },
    { productId: ObjectId('...'), title: 'Кабель USB-C', priceCents: 40000, quantity: 2 },
  ],
}

Читання замовлення – один запит без JOIN, і це головна сила: документ зібраний так, як його споживає застосунок. Ціна: назва товару скопійована в документ. Якщо товар перейменували, старі замовлення зберігають стару назву – для історії замовлень це навіть правильно, але це РІШЕННЯ, яке треба ухвалити свідомо, а не отримати випадково.

Критерії вибору

Критерій Схиляє до SQL Схиляє до NoSQL (документи)
Зв'язки Багато зв'язків «багато-до-багатьох», запити з різних боків Дані читаються цілісними агрегатами
Консистентність Критична (гроші, залишки, бронювання) Прийнятна eventual consistency
Схема Стабільна, спільна для команд Часто змінюється, різнорідні об'єкти
Запити Заздалегідь невідомі, аналітика, звіти Відомі наперед, прості за ключем
Транзакції Між кількома сутностями регулярно Здебільшого в межах одного документа

І чесне доповнення для співбесіди: у більшості продуктових задач PostgreSQL – розумний вибір за замовчуванням, бо покриває і JSON-поля, і повнотекстовий пошук, і горизонтальне читання через репліки. NoSQL обирають під конкретний профіль навантаження, а не «на всяк випадок».

ACID простими словами

  • Atomicity – транзакція виконується повністю або не виконується взагалі. Списання коштів і створення замовлення не можуть «розійтися».
  • Consistency – після транзакції дані відповідають правилам схеми (унікальність, зовнішні ключі, CHECK).
  • Isolation – паралельні транзакції не бачать проміжних станів одна одної. Рівні ізоляції – компроміс між строгістю і швидкістю.
  • Durability – закомічені дані переживають падіння сервера.

Практичний приклад для відповіді: два покупці одночасно купують останню одиницю товару. Без ізоляції обидва побачать «є 1 шт» і обидва оформлять замовлення. Транзакція з блокуванням рядка або перевіркою залишку в UPDATE вирішує це на рівні бази.

Типові міфи

  • «NoSQL швидший». Швидшим є читання одного документа без JOIN. Але запит «усі замовлення з товаром X за місяць» у документній моделі може вимагати сканування всієї колекції. Швидкість залежить від відповідності моделі й запитів, а не від класу бази.
  • «SQL не масштабується». Реляційні бази масштабуються реплікацією на читання і шардингом; величезні продукти живуть на PostgreSQL і MySQL. Складнішим є саме шардинг із транзакціями між шардами, і чесно назвати це обмеження – плюс на співбесіді.
  • «У NoSQL немає транзакцій». У MongoDB транзакції на кілька документів існують; але модель даних зазвичай будують так, щоб вони були рідкістю. Деталі – в офіційній документації MongoDB.
  • «Схема в NoSQL не потрібна». Схема є завжди, питання лише де: у базі чи в коді застосунку. «Schemaless» означає, що помилки схеми виявляться в runtime.

А що з JSON у PostgreSQL?

Окреме питання, яке любить середина співбесіди: «навіщо тоді NoSQL, якщо в PostgreSQL є JSONB?» Чесна відповідь: JSONB закриває значну частину кейсів «гнучкої» частини даних – атрибути товарів різних типів, налаштування користувача, сирі payload-и вебхуків. Можна індексувати поля всередині JSON і поєднувати їх зі звичайними реляційними колонками:

CREATE TABLE products (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  title TEXT NOT NULL,
  attributes JSONB NOT NULL DEFAULT '{}'
);

-- Індекс під пошук за атрибутом
CREATE INDEX idx_products_brand ON products ((attributes->>'brand'));

Це не робить документні бази непотрібними, але ще раз підтверджує правило за замовчуванням: почни з PostgreSQL, ускладнюй інфраструктуру лише під виміряну потребу.

Сильна vs слабка відповідь

Питання: «Яку базу ти б обрав для сервісу замовлень?»

Слабко: «MongoDB, бо він швидкий і в ньому зручний JSON».

Сильно: «Спершу подивився б на дані й операції. Замовлення пов'язані з користувачами й товарами, потрібні транзакції на списання залишків і звіти по продажах – це аргументи за PostgreSQL. Якщо б окремим сервісом був, наприклад, кошик або стрічка переглядів, де дані читаються одним агрегатом і транзакцій між сутностями немає, там документна база або Redis доречніші. За замовчуванням почав би з PostgreSQL і виносив окремі профілі навантаження за потреби».

Різниця не в правильній назві, а в ході міркування: дані → операції → гарантії → вибір.

Типові помилки у відповідях

  1. Бінарне мислення. «SQL для серйозних систем, NoSQL для стартапів» – ярлики замість аналізу. Реальні системи комбінують: PostgreSQL як джерело правди, Redis для кешу, іноді документна база під окремий профіль.
  2. Ігнорування запитів. Кандидат моделює дані, не спитавши, ЯК вони читатимуться. А саме запити визначають, чи буде модель зручною: документна база чудова рівно до першого «а тепер звіт у розрізі товарів».
  3. Денормалізація без плану оновлення. Скопіював назву товару в документ замовлення – добре; не відповів, що станеться при перейменуванні – мінус. Кожна копія даних має власника і правило життя.
  4. «Транзакції не потрібні, у нас простий продукт». Достатньо одного переказу коштів, бронювання чи ліміту місць, щоб вони стали потрібні. Краще показати, що ти бачиш такі місця заздалегідь.
  5. Індекси поза увагою. Різниця між «працює» і «працює на реальних даних» – найчастіше саме індекси. Згадка про EXPLAIN і індекс під конкретний запит одразу піднімає рівень відповіді.

Що потренувати перед співбесідою

  1. Напиши схему з прикладу вище руками і три JOIN-запити до неї (документація PostgreSQL – найкращий довідник).
  2. Змоделюй ту саму область документами і сформулюй, які запити стали простішими, а які болючішими.
  3. Підготуй по одному прикладу задачі «точно SQL» і «точно документи» зі своїм поясненням.

База даних – лише один шар backend-співбесіди; повний маршрут підготовки є в статті про Node.js interview, а про кешування поверх бази – у розборі Redis. Якщо готуєшся системно, глянь і план підготовки за 30 днів.