# Спроєктувала рівень даних PostgreSQL, побудований насамперед на функціях — 1 275 збережених функцій у 34 схемах — щоб кожне читання й кожен запис проходили через функцію, на яку база даних може видати права, а не через таблицю.

2025

**Ситуація.** Бізнес‑логіка має звичку просочуватися. Трохи осідає в API, трохи — в SQL‑запиті, який обробник виконує просто на місці, і незабаром те саме правило вже записане двома‑трьома дещо різними способами, а місця, на яке можна вказати й сказати: «ось що система робить зі своїми даними», — немає. Саме так у систему потрапляють баги й діри в безпеці.

**Завдання.** Мета — зібрати все це в одному місці: кожне читання й кожен запис проходять через базу даних, API лишається тонким адаптером, що не знає бізнес‑правил, а всю систему можна наглухо замкнути.

**Дія.** Рівень даних побудовано за принципом function‑first. Схему поділено за доменами — identity, organization, review, message, notification і ще 29, разом 34, — і кожна операція застосунку — це одна з 1 275 функцій PostgreSQL, які він викликає; прямого доступу до таблиць із Go немає взагалі. А дотримання цього правила забезпечує сама база даних. Роль mariner, під якою API входить у базу, має привілей EXECUTE для функцій застосунку та USAGE для схем — і більше нічого: жодного SELECT, жодного INSERT, жодної змоги торкнутися таблиці напряму, — тож замість одного загального гранту виходить приблизно 4 000 явних. Функції працюють у режимі SECURITY DEFINER і належать окремій ролі function_owner без права входу, із зафіксованим search_path, а обліковий запис суперкористувача зарезервовано для міграцій і cron, подалі від запущеного застосунку.

**Результат.** Логіка живе в одному місці, яке справді можна піддати аудиту, API лишається тонким і нудним у хорошому сенсі, а межу доступу стереже сам Postgres, а не сподівання, що всі пам'ятатимуть правила. Навіть якби API якось скомпрометували, через нього однаково не вдалося б зробити нічого, чого не дозволяють функції. Коли функцій 1 275, ця дисципліна має відчутну ціну — нове поле означає міграцію та зміну функції, а не рядок у запиті, — і цим тертям платять за те, що межа тримається.

---

- Роль: Інженер баз даних
- Категорії: [Архітектура платформи](https://data.engineer.company/uk/categories/platform-architecture/), [Backend‑розробка](https://data.engineer.company/uk/categories/backend/), [Бази даних](https://data.engineer.company/uk/categories/databases/), [PostgreSQL](https://data.engineer.company/uk/categories/postgresql/), [SQL](https://data.engineer.company/uk/categories/sql/), [Управління даними](https://data.engineer.company/uk/categories/data-governance/), [Безпека](https://data.engineer.company/uk/categories/security/)
- Послуги: [Архітектура платформи та рішень](https://data.engineer.company/uk/services/platform-architecture/), [Backend- та API‑розробка](https://data.engineer.company/uk/services/backend-development/), [Проєктування та моделювання баз даних](https://data.engineer.company/uk/services/database-design/), [Data Governance та якість даних](https://data.engineer.company/uk/services/data-governance/)

<https://data.engineer.company/uk/portfolio/designed-a-postgresql-function-first-data-layer-across-63/>
