# Бекенд

## Що це таке

Бекенд — це частина програмної системи, яка працює на машинах під контролем її оператора: він
зберігає дані, застосовує правила про те, кому що дозволено, і відповідає на запити від браузерів,
застосунків та інших сервісів. Англійською його також пишуть back end або back-end, а ту саму
територію часто називають серверною стороною, server side.

У термінах HTTP бекенд — це те, що RFC 9110 називає origin server: програма, яка може створювати
авторитетні відповіді для певного target resource. Документ W3C Architecture of the World Wide Web
додає погляд читача. URI ідентифікує ресурс, а до браузера вирушає його представлення, дані, що
кодують інформацію про стан ресурсу. Клієнт бачить сторінку замовлення, а бекенд зберігає
замовлення, залишки на складі й оплату та вирішує, що потрапить у відповідь.

Зазвичай бекенд надає API, набір HTTP-endpoints, які може викликати фронтенд, мобільний застосунок
або система іншої компанії. API — це контракт: які шляхи існують, що приймає кожен із них, що
повертає і які помилки може видати. OpenAPI Specification — поширений спосіб записати цей контракт у
вигляді опису, незалежного від мови програмування, з якого інструменти генерують клієнти,
документацію й тести. За API робота зазвичай поділена на шари: обробку запитів, бізнес-логіку й
зберігання.

## Чому це важливо

Перше питання — чи потрібен системі взагалі бекенд, що працює в момент запиту. Сторінку, однакову
для кожного відвідувача, можна згенерувати один раз і віддавати як файли. Бекенд, що працює
постійно, виправдовує себе, коли запит має щось змінити або залежить від того, хто його надіслав:
замовлення, вхід в обліковий запис, пошук у приватних даних. До того ж він коштує грошей щодня, бо
програму, яка відповідає на запити з інтернету, треба захищати, оновлювати й оплачувати.

Друге — довіра. Бекенд працює на машинах, які контролює оператор, тому саме там правило можна
справді забезпечити. Будь-яку перевірку у фронтенді обійде той, хто надсилає запити напряму, тож
кожне важливе правило, від ціни до дозволу, перевіряють на сервері щодо користувача, який увійшов, і
конкретного запису. OWASP Application Security Verification Standard перетворює це на вимоги, за
якими команда може будувати й тестувати.

Третє — де живе логіка. Правило, розкидане між обробником, сервісним класом і тригером у базі даних,
має три місця для змін і три копії, які розходяться. Одні команди тримають правила в коді
застосунку, а базу використовують для зберігання; інші переносять правила й формування даних у базу
і тримають API тонким. Працювати може і те, і те, якщо кожне правило має один дім.

Четверте — контракт із клієнтами. HTTP дає кожній відповіді код стану з визначеним значенням, і
клієнти, проксі та інструменти моніторингу діють відповідно до нього. Код 422 Unprocessable Content
означає, що запит синтаксично правильний і в підтримуваному форматі, але семантично хибний, як-от
бронювання з датою в минулому. RFC 9457 додає стандартний формат для помилок, problem details:
невеликий об'єкт JSON із полями type, title, status, detail та instance, що надсилається як
`application/problem+json`, щоб клієнт розрізняв помилки без розбору тексту.

## Як це виглядає на практиці

Бекенд однієї платформи
[доручає базі даних будувати кожну відповідь і передає її без змін](/uk/portfolio/designed-a-json-passthrough-architecture-where-postgresql-functions-58/).
Звичний шлях від бази до браузера сторінка називає естафетою перетворень: API розбирає рядки в
structs, перекроює їх і знову серіалізує в JSON. Тут функції PostgreSQL збирають усю відповідь як
JSON там, де вже лежать дані, а обробник на Go отримує її як `json.RawMessage` і пересилає далі як
є. Невелика допоміжна функція `QueryJSON` зробила цей шлях найпростішим. DTO, мапери й структури
відповідей зникли, код обробників став значно коротшим, а зміна в тому, що повертає функція,
доходить до клієнта напряму, і правити код обробника не доводиться.

Для вхідних запитів та сама ідея одного джерела означає, що
[контракт починається з бази даних і поширюється назовні](/uk/portfolio/built-a-request-schema-validation-contract-with-automated-61/).
Схема та її функції задають структури даних, типи Go задають API, Huma генерує з них опис OpenAPI, а
з цього опису генерується типізований клієнт TypeScript на 44 076 рядків. Обмеження, які інтерфейс
застосовує до форми, беруться з того самого джерела, і вручну їх у валідатор ніхто не переносить.
Кожен перехід охороняється, тож поле не може змінитися лише з одного боку: розбіжність ламає
збирання за кілька хвилин після зміни. Ціна, яку називає сторінка, — крок генерації в самому центрі
процесу.

Цей сайт робить протилежний вибір. Він
[повністю генерується на етапі збирання й не має бекенду, що працює під час запитів](/uk/portfolio/built-a-multilingual-static-site-in-hugo-126/).
Чотири його вимоги, серед них робота трьома мовами й нульова вартість утримання, разом виключають
майже всі системи керування вмістом, бо бекенд, який обслуговує запити, доводиться захищати,
оновлювати, оплачувати й описувати на сторінці про конфіденційність. У результаті сайт не має
бекенду, який можна атакувати, і рахунку, який треба сплачувати. Ціна в тому, що все інтерактивне
доводиться розв'язувати на етапі збирання або ніяк, і це вже відсіяло кілька речей, які сервер
зробив би простими.

## Де виникають проблеми

Збої бекенду зазвичай мовчать, доки не надійде запит, якого ніхто не передбачив.

**Користувач змінює запис, що належить комусь іншому.** Endpoint перевіряє, що той, хто викликає,
увійшов, а потім завантажує будь-який ID, названий в URL, тож достатньо змінити в запиті
`/invoices/1041` на `/invoices/1042`. Власність або дозвіл треба перевіряти на сервері для кожного
об'єкта, якого торкається запит, в одному місці, крізь яке проходить кожен обробник, і мати тест, що
просить запис іншого облікового запису й очікує 403 або 404.

**Дія виконується двічі.** Посилання, що скасовує щось через GET-запит, відкриває краулер або
браузер, який завантажує сторінки наперед, і дія відбувається без жодного кліку. RFC 9110 визначає
GET, HEAD, OPTIONS і TRACE як безпечні (safe) методи саме для того, щоб spiders і pre-fetching могли
працювати без ризику завдати шкоди. Інший шлях — повторна спроба: платіжний запит перевищує час
очікування, клієнт надсилає його знову, і покупець платить двічі. Кожну зміну стану варто ставити за
POST, PUT, PATCH або DELETE, а записам, які можуть повторитися, давати ключ, який сервер пам'ятає,
щоб друга копія повертала результат першої.

**Кожна помилка повертається як 500 або як 200 із повідомленням про помилку всередині.** Один
універсальний обробник повідомляє про всі збої однаково, тож моніторинг рахує друкарські помилки як
аварії, а логіка повторних спроб повторює запити, які щоразу завершаться помилкою. Кожен збій варто
зіставити з кодом стану, що його описує: 400 або 422 для поганого введення, 401 і 403 для
ідентичності й дозволів, 404 для відсутнього ресурсу, 409 для конфлікту і 5xx лише для власних збоїв
сервера. Подробиці надсилають як problem details:

```json
{
    "type": "https://example.com/problems/booking-in-past",
    "title": "Booking date is in the past",
    "status": 422,
    "detail": "The date 2026-10-01 is before today.",
    "instance": "/bookings/8812"
}
```

RFC 9457 зазначає, що problem details не є інструментом налагодження базової реалізації, тому
стектрейси й SQL залишаються в журналах сервера.

**Сторінки сповільнюються з ростом даних.** Обробник завантажує список замовлень, а потім для
кожного окремо запитує клієнта, тож сторінка з 50 замовлень робить 51 звернення до бази даних. У
розробці з десятьма рядками це здається швидким, а в продакшні з десятьма тисячами гальмує.
Пов'язані дані варто отримувати одним запитом із join або доручити базі зібрати всю відповідь, і
стежити за кількістю звернень до бази на один запит так само уважно, як за часом відповіді.

## Що почитати далі

- [Architecture of the World Wide Web, Volume One](https://www.w3.org/TR/webarch/) — рекомендація
  W3C про ресурси, представлення та безпечні й небезпечні взаємодії.
- [RFC 9110: HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110) — стандарт IETF про методи,
  коди стану і те, що робить запит безпечним або ідемпотентним.
- [OpenAPI Specification](https://spec.openapis.org/oas/latest.html) — незалежний від мови формат
  опису HTTP API, який читають і люди, і генератори коду.
- [RFC 9457: Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457) — стандартна
  форма JSON для машинозчитуваних відповідей про помилки.
- [OWASP Application Security Verification Standard](https://owasp.org/projects/asvs) — перелік
  вимог безпеки для створення й тестування вебзастосунків.

<https://engineer.company/uk/glossary/backend/>
