Короткий висновок / Пряма відповідь
Архітектурна складність повинна визначатися вартістю перезапуску та гранулярністю відмов, а не модою на розподілені системи. Якщо робота коротка (секунди), має обмежений обсяг, детермінована й дешева для повного перезапуску, розподілена інфраструктура лише додає затримки та точок відмови. Персистентна оркестрація (durable workflows) виправдана лише тоді, коли робота триває хвилини чи години, складається з багатьох незалежних кроків із ненульовою ймовірністю збою зовнішніх API, а частковий перезапуск заощаджує суттєві кошти та час.
Ключові висновки
- Складність інфраструктури повинна слідувати за топологією збоїв: якщо одиничний збій не вимагає часткового відновлення або довготривалого очікування, розподілені черги є передчасною оптимізацією.
- Валідаційний прототип Perfume Engine успішно розв'язав задачу перевірки продуктової гіпотези через монолітний, детермінований конвеєр без баз даних, воркерів та черг повідомлень.
- Дослідження архітектури Big PDF Translator продемонструвало протилежний профіль: багатосторінкові документи роблять вартість повного перезапуску неприпустимою, що робить durable state і чекпоїнти обов'язковими.
- 12-факторна матриця складності дозволяє чітко розмежувати п'ять архітектурних архетипів: синхронний запит, простий background job, персистентний стан завдання, черги з воркерами та повноцінний durable workflow.
- Durable execution (на базі рішень типу Temporal або AWS Step Functions) вирішує проблему надійності за рахунок когнітивної та експлуатаційної складності, яку не можна ігнорувати на ранніх стадіях розробки.
Методологія та доказова база
Порівняльний архітектурний аналіз двох первинних інженерних кейсів із різними профілями відмов (валідаційного прототипу Perfume Engine та дослідницького проєкту Big PDF Translator) у поєднанні з систематизацією 12 факторів вибору моделі виконання.
Аналітичний розбір
Оманлива привабливість передчасної розподіленості
В інженерії штучного інтелекту поширена тенденція переносити складні патерни хмарних платформ у проєкти на ранніх стадіях. Поява нового AI-функціоналу часто супроводжується миттєвим розгортанням розподілених брокерів повідомлень (Kafka, RabbitMQ), баз даних векторного пошуку, оркестраторів завдань (Celery, BullMQ) та спеціалізованих рушіїв тривалих процесів (Temporal, Step Functions).
Проте кожен новий розподілений компонент несе пряму інженерну ціну:
- Необхідність координації консенсусу та підтримки мережевої надійності;
- Складність відтворення станів у локальному середовищі розробки;
- Затримки серіалізації/десеріалізації та черг;
- Необхідність моніторингу черг, тупикових повідомлень (dead-letter queues) та дрейфу версій;
- Суттєве ускладнення трасування й налагодження помилок.
Архітектурний принцип Simple before distributed стверджує: система має залишатися на найпростішому рівні виконання, доки фундаментальні характеристики робочого навантаження не змусять її перейти на наступний щабель складності.
Нижче ми розглянемо два контрастні первинні кейси з нашої практики та систематизуємо 12 факторів прийняття рішень.
Порівняння двох інженерних контурів
Для ілюстрації розглянемо дві системи з діаметрально протилежними вимогами до обробки даних та стійкості до відмов.
Контур A: Валідаційний прототип Perfume Engine
У межах першого валідаційного прототипу Perfume Engine стояло завдання перевірити логіку узгодження ароматів із парфумерними компонентами на базі строгих детермінованих правил та доказового нормалізованого датасету.
Вимоги та характеристики навантаження:
- Обсяг даних: Компактний, повністю нормалізований каталог (десятки ароматів і базових нот).
- Час обчислення: Обчислення матриці схожості та проекції займало менше 50 мілісекунд для повного графа.
- Ймовірність збою: Нульова залежність від зовнішніх мережевих API чи нестабільних моделей під час виконання запиту.
- Вартість перезапуску: Нульова — будь-який запит можна перерахувати миттєво з оперативної пам’яті.
Архітектурне рішення: Система була реалізована як автономна детермінована функція без зовнішньої бази даних, без фонових воркерів і без черг повідомлень. Дані імпортувалися як незмінний артефакт, а публічний шар працював як швидка синхронна проекція в пам’яті. Впровадження Redis, черг чи Celery в цей контур створило б надмірний оверхед без жодної користі для надійності чи швидкодії.
Контур B: Дослідження архітектури Big PDF Translator
У дослідницькому проєкті системи перекладу великих PDF-документів технічні характеристики робочого навантаження виявилися фундаментально іншими.
Вимоги та характеристики навантаження:
- Обсяг та тривалість: Документи обсягом від 100 до 1 000+ сторінок; повний цикл розпізнавання, сегментації, багатокрокового перекладу та верстки може тривати від 15 хвилин до кількох годин.
- Сторонні залежності: Сотні послідовних і паралельних викликів зовнішніх OCR та Translation API з жорсткими rate limits, квотами та періодичними мережевими таймаутами (HTTP 429, 502, 504).
- Гранулярність відмов: Збій на 850-й сторінці не повинен призводити до анулювання результатів попередніх 849 сторінок.
- Вартість перезапуску: Повний повторний запуск 1 000-сторінкового документа коштує десятки доларів на викликах API та години очікування користувача.
Архітектурне рішення:
У такому контурі просте синхронне виконання або примітивний локальний скрипт є неприпустимими. Архітектура вимагає формалізованого DocumentIR, персистентних чекпоїнтів кожного кроку (видобування, переклад, валідація, збірка) та надійного рушія довготривалих робочих процесів (durable orchestration), здатного зберігати стан роками, повторювати індивідуальні кроки та забезпечувати ідемпотентність.
12-факторна матриця складності архітектури
Щоб уникнути суб’єктивних дискусій, ми формалізували 12 критеріїв, за якими інженерна команда може визначити мінімально необхідний рівень складності:
| № | Фактор | Сприяє простій архітектурі (Синхронно / Local Job) | Вимагає складної оркестрації (Queues / Durable Workflows) |
|---|---|---|---|
| 1 | Тривалість виконання | До 5 секунд (вкладається в типовий HTTP timeout) | Хвилини або години (перевищує будь-яке пряме HTTP-з’єднання) |
| 2 | Кількість кроків | 1–2 атомарні операції | Багатокроковий пайплайн із залежностями та розгалуженнями |
| 3 | Вартість перезапуску | Мізерна (мілісекунди CPU, нульова фінансова вартість) | Висока (дорогі виклики LLM/OCR, сотні виконаних сторінок) |
| 4 | Ймовірність збою | Близька до 0 (чиста локальна обчислювальна логіка) | Висока (сторонні нестабільні сервіси, тротлінг, квоти) |
| 5 | Гранулярність retry | Можна повторити всю операцію цілком | Потрібен точковий retry окремого абзацу або сторінки |
| 6 | Збереження прогресу | Проміжний стан не має цінності | Необхідні персистентні чекпоїнти кожного кроку |
| 7 | Скасування та пауза | Не потрібні або достатньо обриву TCP-з’єднання | Потрібна підтримка відкликання, паузи та ручного відновлення |
| 8 | Зовнішні залежності | Відсутні або внутрішня база даних із низьким p99 | 3+ незалежних постачальників API з різними лімітами |
| 9 | Конкурентність / Fan-out | Послідовна обробка або простий локальний пул | Паралельна обробка тисяч дрібних фрагментів (Map-Reduce) |
| 10 | Людський фактор (Human-in-the-loop) | Автоматичне завершення без зовнішнього очікування | Очікування перевірки редактором протягом днів або тижнів |
| 11 | Вимоги до RPO / відновлення | Після падіння процесу клієнт просто повторює запит | Після перезавантаження сервера воркер має продовжити з місця збою |
| 12 | Глибина аудиту та налагодження | Достатньо стандартного логування запитів (ELK / CloudWatch) | Потрібна повна історія подій (Event Sourcing / Workflow Replay) |
П’ять архітектурних архетипів виконання
На основі зазначених факторів формується спектр із п’яти типових архітектурних рішень:
[1. Синхронний запит]
│ (перевищення HTTP timeout, зростання затримок)
▼
[2. Простий Background Job] (in-process / thread pool)
│ (ризик втрати завдань при рестарті, потреба у статусах)
▼
[3. Персистентне завдання в БД] (polling, state machine у реляційній БД)
│ (висока конкурентність, розподілені воркери, пікові навантаження)
▼
[4. Черга повідомлень і пули воркерів] (RabbitMQ, Redis Streams, Celery)
│ (багатокрокові процеси, компенсації, затримки між днями, відновлюваність)
▼
[5. Durable Workflow Orchestration] (Temporal, AWS Step Functions)
1. Синхронний запит (Synchronous Request-Reply)
- Коли використовувати: Детерміновані операції, легка валідація, інференс невеликих локальних моделей, де p99 < 1–2 с.
- Приклад: Ранній прототип Perfume Engine, перевірка правопису коротких фраз, розрахунок математичних формул.
- Переваги: Максимальна простота, відсутність інфраструктури стану, просте тестування.
2. Простий фоновий процес (In-Memory Background Task)
- Коли використовувати: Неблокуючі операції, де втрата поодинокого завдання при плановому перезавантаженні є прийнятною (відправка метрик, оновлення другорядного кешу).
- Переваги: Не вимагає зовнішнього брокера чи бази даних черг.
3. Персистентне завдання у реляційній базі (Database-backed Job State)
- Коли використовувати: Завдання тривають від кількох секунд до хвилини, кількість задач — від одиниць до сотень на хвилину, потрібен статус у UI (
pending,processing,completed,failed). - Переваги: Повний контроль транзакційності за допомогою ACID у PostgreSQL або MySQL. Не потребує адміністрування RabbitMQ чи Kafka, поки обсяги помірні.
4. Асинхронні черги та пули воркерів (Distributed Queue + Workers)
- Коли використовувати: Висока конкурентність, незалежні однорідні завдання, необхідність масштабування обчислювальних нод (наприклад, окремий пул машин із GPU для вилучення эмбеддингів).
- Обмеження: Складно реалізувати багатокрокові залежності та відкат транзакцій (Saga pattern) суто на базі черг без додаткового шару координації.
5. Durable Workflow Orchestration (Event-Sourced Workflows)
- Коли використовувати: Складні тривалі процеси (як у дослідженні Big PDF Translator), де збій на довільному етапі повинен ізолюватися, повторюватися або чекати на дію людини без блокування ресурсів пам’яті.
- Переваги: Повний імунітет до перезавантаження інфраструктури, детерміноване відновлення історії подій, вбудовані політики retry з експоненційним бекофом.
Практичне правило прийняття рішень
Спрощене інженерне правило для архітектора AI-систем виглядає так:
Якщо операцію можна повторити повністю без істотних фінансових чи часових втрат, не будуйте durable workflow.
Якщо ж одиничний збій призводить до повторної оплати $10+ або втрати 30+ хвилин обчислень, durable orchestration окупає свою складність з першого дня.
Складність системи повинна бути відповіддю на фізичні обмеження навантаження, а не наслідком прагнення створити «ідеальний ентерпрайз-стек» до валідації реальної потреби.
Відомі обмеження та граничні умови
Фреймворк базується на аналізі інженерних компромісів та системного проектування. Він не є універсальною формулою розрахунку вартості TCO для довільного стеку та потребує калібрування під конкретні SLA та ліміти хмарних провайдерів.
Джерела та примітки
- [1]
- [2]
Архітектурний консалтинг
Обговорити ці висновки стосовно вашої системи
Індивідуальні архітектурні аудити, перевірка надійності та проєктування рішень без неконтрольованої складності.