← Back to course

PostgreSQL і застосунки: підключаємо базу даних до реальних проєктів

PostgreSQL і застосунки: підключаємо базу даних до реальних проєктів

Повертаємось до PostgreSQL.

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

Ти створив:

customers
categories
products
orders
order_items

Ти використовував:

Дуже добре.

Тепер PostgreSQL — це вже не просто загадкова істота з терміналу.

Він стає реальним інструментом.

Але залишається одне дуже важливе питання:

Як застосунок реально підключається до PostgreSQL?

Бо в реальних проєктах користувачі не відкривають psql і не пишуть SQL вручну.

Зазвичай.

Backend-застосунок підключається до бази даних.

Потім застосунок читає дані.

Записує дані.

Оновлює дані.

Видаляє дані.

Сподіваємось, не всі дані.

Бо це був би дуже драматичний вівторок.

Сьогодні ми вивчимо, як застосунки підключаються до PostgreSQL.

Ця лекція не про один конкретний framework.

Ці ідеї підходять для:

Django
Spring Boot
Node.js
Express
NestJS
Laravel
Rails
Go-застосунків
будь-якого backend, якому потрібен PostgreSQL

Framework-и змінюються.

Принципи підключення залишаються.

Дуже корисно.

Дуже база даних.

Дуже “будь ласка, не пиши пароль прямо в коді”.

Що ти вивчиш

У цій лекції ти вивчиш:

До кінця цієї лекції ти зрозумієш міст між PostgreSQL і backend-застосунками.

Бо база даних без застосунку корисна.

Але база даних, підключена до застосунку, стає потужною.

Як склад, підключений до магазину.

Або як кавомашина, підключена до втомленого розробника.

Важлива інфраструктура.

Базова ідея

Застосунку потрібна інформація для підключення, щоб говорити з PostgreSQL.

Зазвичай потрібні:

host
port
назва бази даних
username
password

Приклад:

host: localhost
port: 5432
database: shop_db
username: shop_user
password: strong_password

Застосунок використовує ці значення, щоб відкрити підключення.

Потім він може надсилати SQL-запити.

Наприклад:

SELECT * FROM products;

Застосунок надсилає запит.

PostgreSQL виконує його.

PostgreSQL повертає результат.

Застосунок використовує результат.

Можливо, показує продукти на сайті.

Можливо, створює API-відповідь.

Можливо, генерує звіт.

Можливо, ламається, бо хтось забув крапку з комою.

Класика.

Host PostgreSQL

Host каже застосунку, де працює PostgreSQL.

Для локальної розробки host часто такий:

localhost

або:

127.0.0.1

Це означає:

PostgreSQL працює на тій самій машині, що й застосунок.

Приклад:

host=localhost

У production PostgreSQL може працювати на іншому сервері.

Приклад:

host=db.example.com

або:

host=10.0.0.5

або всередині Docker:

host=postgres

Host залежить від того, де живе база даних.

Застосунок має знати правильну адресу.

Інакше він стукатиме не в ті двері.

PostgreSQL не відповість з будинку, де він не живе.

Дуже логічно.

Port PostgreSQL

PostgreSQL зазвичай слухає порт:

5432

Тому типове підключення використовує:

port=5432

Порт — це як номер дверей на сервері.

Сервер може запускати багато сервісів.

PostgreSQL за замовчуванням використовує порт 5432.

Якщо ти змінив порт, треба використовувати новий.

Але для початківців у більшості випадків відповідь така:

5432

Рідкісний момент простоти.

Насолоджуйся.

Назва бази даних

Один сервер PostgreSQL може містити багато баз даних.

Наприклад:

learning_postgresql
shop_db
portfolio_db
blog_db

Твій застосунок має знати, яку базу використовувати.

Приклад:

database=shop_db

Якщо застосунок підключиться до неправильної бази, почнуться дивні речі.

Таблиць може не бути.

Дані можуть виглядати старими.

Твій мозок може почати debug не того всесвіту.

Завжди перевіряй назву бази даних.

Маленька помилка.

Великий головний біль.

Username і password

PostgreSQL використовує користувачів і паролі для контролю доступу.

Приклад:

username=shop_user
password=strong_password

Користувач визначає, що застосунок може робити.

Користувач може мати права на:

підключення до бази даних
читання таблиць
додавання рядків
оновлення рядків
видалення рядків
створення таблиць

Не давай кожному застосунку повні права superuser.

Це як дати дитині бензопилу, бо вона хотіла розрізати аркуш паперу.

Технічно ефективно.

Глибоко нерозумно.

Не використовуй користувача postgres у застосунках

PostgreSQL часто має адміністративного користувача за замовчуванням:

postgres

Цей користувач потужний.

Дуже потужний.

Занадто потужний для звичайних застосунків.

Не використовуй postgres як користувача свого застосунку.

Замість цього створи окремого користувача для застосунку.

Приклад:

shop_user
blog_user
app_user
portfolio_user

Чому?

Бо якщо застосунок має bug або його атакують, ти хочеш обмежити шкоду.

Користувач застосунку має мати тільки ті права, які йому потрібні.

Не ключі від усього королівства.

У королівстві бази даних є дракони.

І рахунки.

Створюємо базу даних для застосунку

Відкрий PostgreSQL як користувач postgres:

sudo -iu postgres psql

Створи базу даних:

CREATE DATABASE shop_db;

Створи користувача:

CREATE USER shop_user WITH PASSWORD 'change_this_password';

Дай користувачу доступ до бази:

GRANT CONNECT ON DATABASE shop_db TO shop_user;

Тепер підключись до бази:

\c shop_db

Дай права на schema public:

GRANT USAGE ON SCHEMA public TO shop_user;

Дозволь користувачу працювати з таблицями:

GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO shop_user;

Дозволь користувачу використовувати sequences.

Це важливо для SERIAL ID.

GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO shop_user;

Для майбутніх таблиць можна встановити default privileges:

ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO shop_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO shop_user;

Це вже набагато краще, ніж використовувати superuser postgres.

Застосунок отримує доступ.

Але не безмежну владу.

Дуже цивілізовано.

Тестуємо нового користувача

Вийди з PostgreSQL:

\q

Тепер спробуй підключитися як новий користувач:

psql -h localhost -U shop_user -d shop_db

PostgreSQL попросить пароль.

Введи пароль, який ти створив.

Якщо підключення працює, ти потрапиш у psql.

Потім перевір:

SELECT current_user;

Ти маєш побачити:

shop_user

Добре.

Тепер твій застосунок теж може використовувати цього користувача.

Двері бази даних відкриваються.

Але тільки правильним ключем.

Дуже безпечно.

Дуже доросло.

Що таке connection string?

Connection string збирає всю інформацію для підключення в один рядок.

Типовий формат PostgreSQL:

postgresql://username:password@host:port/database

Приклад:

postgresql://shop_user:change_this_password@localhost:5432/shop_db

Він містить:

username: shop_user
password: change_this_password
host: localhost
port: 5432
database: shop_db

Багато інструментів і framework-ів використовують connection string.

Вони компактні.

Корисні.

І небезпечні, якщо їх вставляти всюди.

Бо вони містять паролі.

Стався до connection string як до ключів.

Не публікуй їх.

Не commit їх на GitHub.

Не надсилай випадковим людям.

Не вставляй їх у screenshots.

Майбутній ти скаже дякую.

Люди з безпеки теж перестануть кричати.

Змінні середовища

Застосунки зазвичай читають налаштування бази даних зі змінних середовища.

Змінні середовища — це значення, які зберігаються поза кодом.

Приклад:

DB_HOST=localhost
DB_PORT=5432
DB_NAME=shop_db
DB_USER=shop_user
DB_PASSWORD=change_this_password

Або:

DATABASE_URL=postgresql://shop_user:change_this_password@localhost:5432/shop_db

Навіщо використовувати змінні середовища?

Бо код не має містити секрети.

Погано:

пароль прямо в source code

Добре:

пароль у змінній середовища

Це дозволяє використовувати різні налаштування для:

локальної розробки
тестів
production

Той самий код.

Інша конфігурація.

Дуже корисно.

Дуже професійно.

Дуже “я навчився після болючих помилок”.

Файл .env

Під час локальної розробки багато проєктів використовують файл .env.

Приклад:

DB_HOST=localhost
DB_PORT=5432
DB_NAME=shop_db
DB_USER=shop_user
DB_PASSWORD=change_this_password

Або:

DATABASE_URL=postgresql://shop_user:change_this_password@localhost:5432/shop_db

Застосунок читає цей файл при запуску.

Важливо:

Не commit файли .env з реальними паролями.

Додай .env до .gitignore.

Приклад .gitignore:

.env
.env.local
.env.production

Можна створити безпечний приклад:

.env.example

Приклад:

DB_HOST=localhost
DB_PORT=5432
DB_NAME=shop_db
DB_USER=shop_user
DB_PASSWORD=your_password_here

Це показує іншим розробникам, які змінні потрібні.

Але не відкриває реальні секрети.

Хороша практика.

Дуже хороша.

Золота зірочка.

Базоданна золота зірочка.

Приклад: загальні налаштування застосунку

Багатьом застосункам потрібні такі налаштування:

DB_HOST=localhost
DB_PORT=5432
DB_NAME=shop_db
DB_USER=shop_user
DB_PASSWORD=change_this_password

Потім застосунок створює підключення.

Концептуально:

Підключись до DB_HOST на DB_PORT.
Використай DB_NAME.
Увійди з DB_USER і DB_PASSWORD.

Деякі framework-и віддають перевагу одному URL:

DATABASE_URL=postgresql://shop_user:change_this_password@localhost:5432/shop_db

Обидва стилі поширені.

Який використовувати — залежить від framework.

Але ідея однакова.

Твоєму застосунку потрібні координати бази даних.

Без координат він блукає як турист зі зламаним GPS.

Приклад: Django settings

У Django налаштування бази даних часто виглядають так:

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "shop_db",
        "USER": "shop_user",
        "PASSWORD": "change_this_password",
        "HOST": "localhost",
        "PORT": "5432",
    }
}

Але писати пароль прямо тут — погана ідея.

Краще так:

import os

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": os.environ.get("DB_NAME"),
        "USER": os.environ.get("DB_USER"),
        "PASSWORD": os.environ.get("DB_PASSWORD"),
        "HOST": os.environ.get("DB_HOST", "localhost"),
        "PORT": os.environ.get("DB_PORT", "5432"),
    }
}

Тепер пароль приходить зі змінних середовища.

Набагато краще.

Django отримує дані для підключення.

Код залишається безпечнішим.

Усі менше нервують.

Крім, можливо, CSS-розробника.

Але це вже інший курс.

Приклад: Spring Boot settings

У Spring Boot application.properties може виглядати так:

spring.datasource.url=jdbc:postgresql://localhost:5432/shop_db
spring.datasource.username=shop_user
spring.datasource.password=change_this_password

Краще зі змінними середовища:

spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASSWORD}

Тоді твоє середовище може містити:

DB_URL=jdbc:postgresql://localhost:5432/shop_db
DB_USER=shop_user
DB_PASSWORD=change_this_password

Це набагато безпечніше, ніж hardcode секретів.

У реальних проєктах пароль бази даних не має жити в Git repository.

Git пам’ятає все.

Як слон.

Але з історією commit-ів.

Приклад: Node.js connection

Node.js застосунок може використовувати connection string:

DATABASE_URL=postgresql://shop_user:change_this_password@localhost:5432/shop_db

Потім застосунок читає його.

Концептуально:

const connectionString = process.env.DATABASE_URL;

Багато Node.js бібліотек підтримують цей стиль.

Важлива ідея не в конкретній бібліотеці.

Важлива ідея така:

Читай секрети зі змінних середовища.
Не hardcode їх у коді.

Це правило йде за тобою через усі мови.

Python.

Java.

JavaScript.

Go.

PHP.

Всюди.

Секрети в коді — як відкриті вікна взимку.

Погана ідея.

Потім дорого.

Локальна розробка vs production

Локальна розробка зазвичай означає:

застосунок і база даних працюють на твоєму комп’ютері
host = localhost
port = 5432

Production зазвичай означає:

застосунок працює на сервері
база даних може працювати на іншому сервері
host не localhost
пароль сильніший
безпека важливіша
backup-и важливіші
monitoring важливіший

У локальній розробці помилки дратують.

У production помилки стають рахунками.

Дуже мотивує.

Саме тому конфігурація має бути гнучкою.

Ти можеш мати:

локальну базу даних
тестову базу даних
production базу даних

Кожне середовище має різні значення.

Той самий код застосунку.

Різні змінні середовища.

Це нормально.

Це професійно.

Так ми не змінюємо код тільки для того, щоб підключитися кудись інакше.

Docker і host names PostgreSQL

Якщо твій застосунок і PostgreSQL працюють у Docker Compose, host часто є назвою service.

Приклад:

services:
  app:
    environment:
      DB_HOST: postgres
      DB_PORT: 5432

  postgres:
    image: postgres

Всередині Docker застосунок може підключатися до:

postgres

а не до:

localhost

Чому?

Бо всередині container застосунку localhost означає сам container застосунку.

Не PostgreSQL container.

Це дуже часта помилка.

Дуже часта.

Дуже болюча.

Дуже Docker.

Просте правило:

З твого комп’ютера: localhost може працювати.
З іншого container: використовуй назву service.

Тому в Docker Compose host бази даних може бути:

postgres

або:

db

залежно від назви service.

Docker networking потужний.

І часом гостренький.

Типові помилки підключення

Connection refused

Приклад помилки:

connection refused

Зазвичай це означає:

PostgreSQL не запущений.
Неправильний host.
Неправильний port.
PostgreSQL не слухає там.
Firewall блокує підключення.

Перевір статус PostgreSQL:

systemctl status postgresql

На деяких системах назва service може відрізнятися.

Також можна спробувати:

psql -h localhost -U shop_user -d shop_db

Якщо psql не може підключитися, твій застосунок, ймовірно, теж не зможе.

Не звинувачуй framework одразу.

Спочатку перевір базу даних.

Framework-и часто винні.

Але не завжди.

Password authentication failed

Приклад помилки:

password authentication failed for user

Зазвичай це означає:

неправильний username
неправильний password
користувача не існує
змінна середовища має неправильне значення

Перевір username:

SELECT current_user;

Перевір, чи користувач існує:

\du

Якщо потрібно, зміни пароль:

ALTER USER shop_user WITH PASSWORD 'new_password_here';

Потім онови змінну середовища.

Не оновлюй тільки свою пам’ять.

Застосунки не читають твою пам’ять.

На щастя.

Database does not exist

Приклад помилки:

database "shop_db" does not exist

Зазвичай це означає саме те, що написано.

Перевір бази даних:

\l

Створи базу, якщо потрібно:

CREATE DATABASE shop_db;

Або виправ назву бази в конфігурації.

Ця помилка часто є просто typo.

Маленьке typo з великою особистістю.

Permission denied

Приклад помилки:

permission denied for table products

Це означає, що користувач успішно підключився.

Але не має прав зробити щось.

Дай права:

GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO shop_user;

Для sequences:

GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO shop_user;

Якщо застосунок може читати, але не може вставляти рядки з SERIAL ID, проблема може бути в правах на sequences.

Права PostgreSQL потужні.

І трохи дратівливі.

Як серйозний охоронець із паперами.

Table does not exist

Приклад помилки:

relation "products" does not exist

Можливі причини:

Ти підключився до неправильної бази даних.
Таблицю не створено.
Таблиця в іншій schema.
Migration не запущена.
Назва таблиці інша.

Перевір таблиці:

\dt

Перевір поточну базу даних:

SELECT current_database();

Ця помилка часто трапляється, коли застосунок підключається до однієї бази, а ти створив таблиці в іншій.

Класика.

Болюче.

Дуже навчально.

Базові правила безпеки

Ось прості правила.

Не advanced security.

Базове виживання.

Не hardcode паролі

Погано:

пароль у source code

Добре:

пароль у змінній середовища

Код можна поширювати.

Секрети — ні.

Дуже просто.

Дуже часто ігнорується.

Дуже небезпечно.

Не commit .env

Додай .env до .gitignore.

.env
.env.local
.env.production

Якщо ти випадково commit реальний пароль, зміни його.

Не просто видаляй файл з останнього commit і не роби вигляд, що нічого не сталося.

Git history пам’ятає.

Git у цій ситуації не твій друг.

Git — свідок.

Використовуй окремого користувача бази даних

Не використовуй superuser postgres у застосунку.

Створи app-specific user:

shop_user

Дай йому тільки потрібні права.

Це обмежує шкоду, якщо щось піде не так.

А щось колись піде не так.

Це не песимізм.

Це software development.

Використовуй сильні паролі

Не використовуй:

password
123456
postgres
admin
qwerty

Це не паролі.

Це запрошення.

Використовуй сильні паролі.

Особливо в production.

Твоя база даних заслуговує на краще.

Тримай production database приватною

Production PostgreSQL database зазвичай не має бути відкритою для всього інтернету.

Краще:

private network
firewall rules
limited IP access
secure hosting configuration

Якщо база даних доступна публічно, безпека стає набагато серйознішою.

Бази даних люблять приватність.

Користувачі теж.

Юристи теж.

Application migrations

Багато framework-ів використовують migrations.

Migration — це контрольована зміна бази даних.

Приклади:

створити таблицю
додати колонку
змінити тип колонки
створити індекс
видалити таблицю

Замість того, щоб щоразу вручну змінювати базу даних, framework відстежує зміни.

Django має migrations.

Spring Boot часто використовує Flyway або Liquibase.

Node.js ORM-и теж мають migration tools.

Ідея така:

Структура бази даних має бути versioned.

Це важливо, бо застосунок і база даних мають збігатися.

Якщо код очікує колонку email, а база її не має, застосунок ламається.

Дуже впевнено.

Migrations допомагають тримати структуру під контролем.

Це не магія.

Але краще, ніж випадкові ручні зміни опівночі.

ORM vs Raw SQL

Багато застосунків використовують ORM.

ORM означає Object-Relational Mapping.

Приклади:

Django ORM
Hibernate / JPA
Prisma
TypeORM
Sequelize
SQLAlchemy

ORM дозволяє працювати з рядками бази даних як з об’єктами.

Приклад ідеї:

Product object
Customer object
Order object

ORM генерує SQL.

Це зручно.

Але все одно треба розуміти SQL.

Чому?

Бо коли щось стає повільним або ламається, ORM не врятує твою душу.

Він згенерує SQL.

PostgreSQL виконає SQL.

Проблеми продуктивності все одно залишаються SQL-проблемами.

Тому вивчення SQL — це не марна трата часу.

Навіть якщо ти використовуєш ORM.

Особливо якщо ти використовуєш ORM.

Бо тепер ти знаєш, що відбувається під ковдрою.

А іноді під ковдрою живе monster query.

Типовий flow застосунку

Типовий backend flow виглядає так:

Користувач відкриває сайт.
Frontend надсилає request до backend.
Backend підключається до PostgreSQL.
Backend виконує query.
PostgreSQL повертає дані.
Backend повертає JSON або HTML.
Frontend показує результат.

Приклад:

GET /products

Backend query:

SELECT
  p.id,
  p.name,
  p.price,
  c.name AS category_name
FROM products AS p
JOIN categories AS c
ON p.category_id = c.id
ORDER BY p.name;

Backend повертає JSON:

[
  {
    "id": 1,
    "name": "Laptop",
    "price": 900.00,
    "category": "Electronics"
  }
]

Так PostgreSQL стає частиною застосунку.

Користувач ніколи не бачить SQL.

Але SQL робить роботу.

Як працівник за кулісами.

Тихий.

Важливий.

Трохи недооцінений.

Connection pooling

Відкрити підключення до бази даних займає час.

Якщо кожен request відкриває нове підключення і одразу закриває його, продуктивність може постраждати.

Багато застосунків використовують connection pool.

Connection pool тримає кілька відкритих підключень до бази даних і повторно їх використовує.

Проста ідея:

Не створюй нове підключення щоразу.
Повторно використовуй існуючі підключення.

Більшість framework-ів робить це за тебе.

Але добре знати ідею.

Бо production systems дуже уважно ставляться до підключень.

Занадто багато підключень може перевантажити PostgreSQL.

Занадто мало підключень може сповільнити застосунок.

Баланс важливий.

Як кава.

Замало — погано.

Забагато — і ти чуєш кольори.

Практика

Створи нову базу даних:

CREATE DATABASE app_demo_db;

Створи нового користувача:

CREATE USER app_demo_user WITH PASSWORD 'change_this_password';

Дай право підключення:

GRANT CONNECT ON DATABASE app_demo_db TO app_demo_user;

Підключись до бази:

\c app_demo_db

Створи просту таблицю:

CREATE TABLE messages (
  id SERIAL PRIMARY KEY,
  title VARCHAR(150) NOT NULL,
  content TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Дай права на schema:

GRANT USAGE ON SCHEMA public TO app_demo_user;

Дай права на таблиці:

GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_demo_user;

Дай права на sequences:

GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_demo_user;

Додай test row:

INSERT INTO messages (title, content)
VALUES ('Hello App', 'This row could be read by a backend application.');

Протестуй підключення:

psql -h localhost -U app_demo_user -d app_demo_db

Потім виконай:

SELECT * FROM messages;

Якщо це працює, ти маєш базу даних, користувача, права і робоче підключення.

Це фундамент інтеграції із застосунками.

Не блискучий.

Дуже важливий.

Як хороша електропроводка.

Ніхто її не бачить.

Усі скаржаться, коли вона не працює.

Міні-завдання

Створи базу даних для blog application.

Вимоги:

database name: blog_app_db
user name: blog_app_user
tables: authors, posts

Правила:

Створи базу даних:

CREATE DATABASE blog_app_db;

Створи користувача:

CREATE USER blog_app_user WITH PASSWORD 'change_this_password';

Дай право підключення:

GRANT CONNECT ON DATABASE blog_app_db TO blog_app_user;

Підключись:

\c blog_app_db

Створи таблиці:

CREATE TABLE authors (
  id SERIAL PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  name VARCHAR(100) NOT NULL
);
CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  author_id INTEGER NOT NULL REFERENCES authors(id),
  title VARCHAR(150) NOT NULL,
  content TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Дай права:

GRANT USAGE ON SCHEMA public TO blog_app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO blog_app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO blog_app_user;

Створи корисні індекси:

CREATE INDEX idx_posts_author_id
ON posts(author_id);
CREATE INDEX idx_posts_created_at
ON posts(created_at);

Тепер створи .env.example файл для застосунку:

DB_HOST=localhost
DB_PORT=5432
DB_NAME=blog_app_db
DB_USER=blog_app_user
DB_PASSWORD=your_password_here

Або:

DATABASE_URL=postgresql://blog_app_user:your_password_here@localhost:5432/blog_app_db

Потім дай відповідь:

Які значення безпечно commit?
Які значення мають залишатися секретними?
Чому .env має бути ignored by Git?
Чому застосунок не має використовувати користувача postgres?

Це практично.

Це реально.

Це нудний фундамент, який запобігає захопливим катастрофам.

А в базах даних “нудно” часто означає “добре”.

Дуже добре.

Типові помилки

Використовувати postgres всюди

Не роби цього.

Користувач postgres потрібен для адміністрування.

Твій застосунок має мати власного користувача.

Дай йому тільки потрібні права.

Це базова безпека.

Базова безпека не є optional.

Це як носити взуття в майстерні.

Писати секрети в коді

Погано:

spring.datasource.password=my_real_password

Погано:

"PASSWORD": "my_real_password"

Погано:

const password = "my_real_password";

Використовуй змінні середовища.

Твій код — не сейф.

Забувати права на sequences

Якщо застосунок може вставляти рядки, але падає з помилками прав на sequences, пам’ятай:

GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;

SERIAL використовує sequences.

Sequences потребують прав.

PostgreSQL точний.

Іноді болісно точний.

Підключатися до неправильної бази даних

Завжди перевіряй:

SELECT current_database();

Багато bugs — це просто:

Я створив таблицю в одній базі.
Мій застосунок підключається до іншої бази.

Це болить.

Але дуже поширено.

Неправильно використовувати localhost у Docker

У Docker Compose localhost з container застосунку зазвичай означає container застосунку.

Не container бази даних.

Використовуй назву database service.

Приклад:

postgres

або:

db

Docker не помиляється.

Він просто дуже буквальний.

Як PostgreSQL.

Вони, напевно, добре ладнають.

Підсумок

Сьогодні ти вивчив:

Це важлива лекція.

Тепер ти розумієш, як PostgreSQL підключається до реальних застосунків.

Тут знання бази даних стає backend-силою.

База даних зберігає правду.

Застосунок використовує правду.

Користувач бачить результат.

А десь посередині розробник сподівається, що змінні середовища правильні.

Дуже реально.

Дуже професійно.

Дуже понеділково.

Наступна лекція

У наступній лекції ми поговоримо про backups, restore і базове обслуговування бази даних.

Бо створити базу даних — добре.

Використовувати базу даних — краще.

Але мати можливість відновити дані після проблеми — безцінно.

Backups нудні.

До того дня, коли вони рятують твоє життя.

Тоді вони стають прекрасними.