Розробка мікросервісної архітектури бекенду мобільного застосунку
Перехід від моноліту до мікросервісів — не данина моді, а вирішення конкретних операційних проблем. Коли команда розростається до 15+ осіб, кожен коміт у спільну кодову базу загрожує конфліктами, релізний цикл розтягується на два тижні, а одна «гаряча» фіча (стрімінг, обробка платежів) потребує окремого масштабування — моноліт стає вузьким місцем. Ми спроектували та впровадили мікросервісну архітектуру для 20+ мобільних застосунків із навантаженням до 2 млн MAU. Наш досвід 7 років на ринку та сертифікації AWS і Kubernetes підтверджують експертизу. Правильна декомпозиція знижує latency кінцевих точок на 60–80% і скорочує час виходу нових фіч з двох тижнів до двох днів.
Але мікросервіси — не срібна куля. Більш ніж 40% міграцій закінчуються створенням розподіленого моноліту, який працює гірше за вихідний. Щоб уникнути цього, потрібно розуміти межі застосовності та платити за оверхед усвідомлено. У цій статті розберемо, які антипатерни вбивають мікросервісні проєкти, як правильно декомпозувати домен і що входить у нашу роботу з проектування архітектури.
Де мікросервіси створюють більше проблем, ніж вирішують
Почнемо з антипатернів, тому що саме сюди йде більшість бюджетів.
Distributed monolith. Розбили моноліт на 15 сервісів, але кожен запит мобільного клієнта синхронно чекає ланцюжок викликів: API Gateway → UserService → OrderService → ProductService → PaymentService. Один сервіс лагає — весь запит висить. Це не мікросервісна архітектура, це моноліт через HTTP з додатковим latency overhead. Ознака: сервіси не можуть працювати незалежно, деплой одного потребує координації з іншими.
Grapevine data consistency. OrderService синхронно викликає InventoryService, отримує 200 OK, але між перевіркою залишку та списанням інший запит встиг зайняти останній товар. Race condition на рівні розподіленої системи. Рішення — Saga pattern: або choreography (події через Kafka/RabbitMQ), або orchestration (Temporal, Apache Camel).
Overhead на маленьких командах. Три розробники, п'ять сервісів — кожен деплой потребує оновлення п'яти Docker-образів, п'яти Helm-чартів, п'яти наборів змінних середовища. Velocity падає, помилки конфігурації зростають. Для команди до 8 осіб модульний моноліт (Modular Monolith) або monolith-first з подальшою декомпозицією — чесніше.
Як правильно декомпозувати домен? (Domain-Driven Design)
Bounded Context — основний принцип: кожен сервіс володіє своїми даними і не читає чужу БД напряму. Типова декомпозиція для e-commerce мобільного застосунку:
| Сервіс | Відповідальність | БД |
|---|---|---|
| user-service | Реєстрація, профіль, аутентифікація | PostgreSQL |
| catalog-service | Товари, категорії, пошук | PostgreSQL + Elasticsearch |
| order-service | Замовлення, статуси, історія | PostgreSQL |
| payment-service | Платіжні методи, транзакції | PostgreSQL |
| notification-service | Push, email, SMS | Redis + PostgreSQL |
| media-service | Завантаження та обробка медіа | S3 + PostgreSQL |
Навіщо потрібен API Gateway для мобільного застосунку?
Мобільний клієнт ніколи не знає про топологію сервісів. Один хост, один TLS-сертифікат. Gateway бере на себе: аутентифікацію JWT (не дублюємо в кожному сервісі), rate limiting, роутинг за версіями API, трансформацію запитів.
Технології: Kong (production-proven, плагіни для auth/rate limit/logging), AWS API Gateway якщо інфраструктура в AWS, Traefik для Kubernetes-native рішення. Для команд, які хочуть кастомну логіку — custom Gateway на Go (BFF — Backend for Frontend), особливо якщо мобільний клієнт потребує агрегації даних з кількох сервісів в одну відповідь.
Як асинхронна комунікація покращує продуктивність?
Синхронні виклики між сервісами — тільки там, де результат потрібен негайно (перевірка ліміту перед платежем). Все інше — через message broker.
Apache Kafka для високонавантажених сценаріїв: event sourcing, аудит-лог, стрімінг метрик. Топік order.created — підписані notification-service (відправить push), analytics-service (оновить метрики), loyalty-service (нарахує бали). Кожен незалежно, без coupling.
RabbitMQ для task queue: транскодування відео, генерація PDF, відправка email. Простіше в операційному плані, достатньо для більшості мобільних застосунків.
Кейс: платформа для стрімінгу фітнес-контенту, 200 000 MAU. Вихідний моноліт на Node.js почав давати timeout на /api/workouts/start — там синхронно викликалися: запис у лог, оновлення прогресу, інкремент лічильника переглядів, перевірка ачівок. Декомпозиція: workout-service публікує подію workout.started в Kafka, інші сервіси обробляють асинхронно. Latency endpoint: з 800ms до 40ms — покращення в 20 разів.
Як організувати observability в мікросервісах?
У мікросервісному середовищі без observability ви сліпі. Обов'язковий мінімум:
- Distributed tracing — Jaeger або Zipkin з OpenTelemetry SDK у кожному сервісі. Коли мобільний клієнт скаржиться на повільну відповідь, trace показує, який саме сервіс винен.
- Centralized logging — ELK Stack (Elasticsearch + Logstash + Kibana) або Loki + Grafana. Correlation ID пробрасывается через всі сервіси в заголовках (
X-Trace-ID). - Service mesh — Istio або Linkerd для mTLS між сервісами, circuit breaker, retry, timeout на рівні інфраструктури, без коду.
Як Circuit Breaker захищає мобільного клієнта?
Якщо payment-service деградує, order-service має швидко повернути fallback, а не чекати тайм-ауту 30 секунд. Resilience4j (Java), Polly (.NET), go-circuitbreaker — circuit breaker розмикається після N послідовних помилок, швидко повертає 503, через 30 секунд пробує знову. Мобільний клієнт отримує відповідь за 100ms, а не тайм-аут.
Порівняння підходів до міжсервісної взаємодії
| Параметр | Синхронне (REST/gRPC) | Асинхронне (Kafka/RabbitMQ) |
|---|---|---|
| Latency для клієнта | Зазвичай нижче, якщо ланцюжок короткий | Може бути вище, але більш передбачувано |
| Масштабування | Складніше — потрібно балансувати кожен сервіс | Простіше — брокер автоматично обробляє піки |
| Стійкість до відмов | Низька — один збій блокує все | Висока — відмова споживача не впливає на інших |
| Складність налагодження | Вище — потрібно трасувати кожен виклик | Нижче — події можна повторно відтворювати |
Вибір між Kafka та RabbitMQ: Kafka краще при високих навантаженнях (>100k повідомлень/с) і для event sourcing. RabbitMQ простіше в налаштуванні та підтримці, підходить для task-queues і малих/середніх навантажень (до 50k повідомлень/с). Для більшості мобільних застосунків з MAU до 1 млн достатньо RabbitMQ.
Процес впровадження
Міграція моноліту в мікросервіси — не «переписуємо все разом». Патерн Strangler Fig: новий функціонал — окремий сервіс, старий — поступово вирізається з моноліту. Починаємо з найменш зв'язаних доменів (зазвичай сповіщення, медіа, аналітика).
| Етап | Терміни |
|---|---|
| Проектування архітектури + базова інфраструктура (Gateway, брокер, моніторинг) | 4–6 тижнів |
| Повна декомпозиція продуктового моноліту в 5–8 сервісів з CI/CD | 16–24 тижні |
Що входить у роботу
- Документація архітектури: діаграми C4, опис API, схеми data flow.
- Вибір та налаштування інфраструктури: Kubernetes, CI/CD, моніторинг.
- Розробка core-сервісів (Auth, API Gateway, брокери).
- Міграція першого домену (пілотний проєкт).
- Навчання команди: DDD, патерни, робота з інфраструктурою.
- Підтримка на етапі стабілізації (2–3 місяці).
Якщо ви шукаєте досвідчену команду для проектування мікросервісної архітектури під мобільний застосунок — зв'яжіться з нами. Ми оцінимо ваш проєкт, підберемо оптимальний стек і запропонуємо план поетапної міграції. Отримайте консультацію безкоштовно.
Примітка: для глибокого розуміння патернів рекомендуємо вивчити Saga pattern та Circuit Breaker на Wikipedia.







