Подписывайтесь:

Блог AST-SoftPro

Архитектурные паттерны для бизнес-приложений: монолит, микросервисы, серверлесс

05.07.2026 12 мин чтения
Архитектурные паттерны для бизнес-приложений: монолит, микросервисы, серверлесс

Архитектурные паттерны для бизнес-приложений: монолит, микросервисы, серверлесс

Выбор архитектурного паттерна — одно из самых важных решений на старте проекта. Ошибиться можно в любую сторону: слишком простая архитектура не выдержит роста, а слишком сложная создаст проблемы с самого начала. В этой статье разберём три основных подхода — монолит, микросервисы и серверлесс — и покажем, когда каждый из них оправдан.

Монолит: простой старт

Монолит — это единое приложение, где весь код, бизнес-логика и данные находятся в одном процессе. Все модули общаются через вызовы функций, а не через сеть.

Преимущества монолита:

  • Простота разработки. Один репозиторий, один процесс сборки, один деплой. Новому разработчику не нужно разбираться в инфраструктуре — достаточно запустить pip install -r requirements.txt и python main.py.

  • Простота отладки. Все данные доступны в одном процессе. Можно поставить точку останова в любой функции и отследить весь путь выполнения.

  • Производительность. Вызовы функций внутри процесса быстрее сетевых запросов на порядки. Нет накладных расходов на сериализацию, маршрутизацию и сетевые задержки.

  • Транзакционная целостность. Все операции над данными выполняются в рамках одной транзакции базы данных. Не нужно реализовывать распределённые транзакции.

Пример монолита на FastAPI:

from fastapi import FastAPI, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base

app = FastAPI(title="Shop Monolith")
Base = declarative_base()
engine = create_engine("postgresql://localhost/shop")
Session = sessionmaker(bind=engine)

class Product(Base):
    __tablename__ = "products"
    id = Column(Integer, primary_key=True)
    name = Column(String(255))
    price = Column(Integer)

Base.metadata.create_all(engine)

@app.get("/products/{product_id}")
def get_product(product_id: int, db: Session = Depends(lambda: Session())):
    return db.query(Product).filter(Product.id == product_id).first()

@app.post("/orders")
def create_order(order_data: dict, db: Session = Depends(lambda: Session())):
    # Вся логика в одном месте
    products = [db.query(Product).get(item["id"]) for item in order_data["items"]]
    total = sum(p.price * item["qty"] for p, item in zip(products, order_data["items"]))
    return {"total": total, "status": "created"}

Когда монолит подходит:

  • Команда до 10 разработчиков

  • Проект на стадии поиска продукт-маркет-фита

  • Нагрузка до 1000 RPS

  • Нет необходимости в независимом масштабировании компонентов

Микросервисы: масштабирование через разделение

Микросервисная архитектура предполагает разделение приложения на независимые сервисы, каждый из которых отвечает за конкретную бизнес-функцию и может развиваться отдельно.

Преимущества микросервисов:

  • Независимое масштабирование. Сервис обработки заказов можно масштабировать в 10 раз, не трогая сервис уведомлений.

  • Независимый деплой. Обновление одного сервиса не требует перезапуска всей системы.

  • Изоляция сбоев. Падение сервиса уведомлений не влияет на обработку заказов.

  • Технологическая гибкость. Разные сервисы могут быть написаны на разных языках — Python для ML-сервиса, Node.js для WebSocket-сервера.

Пример: разделение на сервисы

# Сервис заказов (orders-service)
from fastapi import FastAPI
import httpx

app = FastAPI(title="Orders Service")

@app.post("/orders")
async def create_order(order_data: dict):
    # Вызов сервиса продуктов через HTTP
    async with httpx.AsyncClient() as client:
        products = await client.get(
            f"http://products-service/api/products/{order_data['product_id']}"
        )
    return {"status": "created", "product": products.json()}

# Сервис продуктов (products-service)
from fastapi import FastAPI

app = FastAPI(title="Products Service")

@app.get("/api/products/{product_id}")
async def get_product(product_id: int):
    return {"id": product_id, "name": "Product", "price": 999}

Когда микросервисы подходят:

  • Команда от 10+ разработчиков, работающих над разными частями системы

  • Разная нагрузка на компоненты (например, каталог читается в 10 раз чаще, чем заказы)

  • Необходимость независимого обновления частей системы

  • Готовность платить цену за сложность (сетевые задержки, распределённые транзакции, мониторинг)

Цена микросервисов:

  • Сложность отладки. Трейс запроса проходит через 3-5 сервисов. Нужна distributed tracing (Jaeger, OpenTelemetry).

  • Сетевые задержки. Каждый вызов между сервисами — сетевой запрос с задержкой 1-10 мс.

  • Распределённые транзакции. Вместо ACID-транзакций — eventual consistency и saga-паттерны.

  • Операционные расходы. Каждый сервис — отдельный процесс с собственным мониторингом, логированием и CI/CD.

Серверлесс: операционная лёгкость

Серверлесс-архитектура позволяет запускать функции без управления серверами. Вы платите только за время выполнения кода.

Преимущества серверлесса:

  • Нулевая операционная нагрузка. Не нужно управлять серверами, балансировщиками, масштабированием.

  • Автоматическое масштабирование. От 0 до 10 000 параллельных вызовов без вмешательства.

  • Платёж за использование. Если функция не вызывается — вы не платите.

  • Быстрый старт. Написание функции и деплой за минуты.

Пример серверлесс-функции на Python:

import json
import boto3

def lambda_handler(event, context):
    """Обработка заказа при поступлении уведомления"""
    order_id = event["order_id"]

    # Запись в DynamoDB
    dynamodb = boto3.resource("dynamodb")
    table = dynamodb.Table("orders")
    table.put_item(Item={"order_id": order_id, "status": "processing"})

    # Отправка уведомления
    sns = boto3.client("sns")
    sns.publish(
        TopicArn="arn:aws:sns:us-east-1:123456789:orders",
        Message=json.dumps({"order_id": order_id}),
    )

    return {"statusCode": 200, "body": json.dumps({"status": "ok"})}

Когда серверлесс подходит:

  • Непредсказуемая нагрузка (пиковые нагрузки раз в неделю)

  • Фоновые задачи (обработка изображений, генерация отчётов)

  • Webhook-обработчики

  • MVP с минимальными операционными затратами

Ограничения серверлесса:

  • Cold start (холодный старт). Первый вызов после простоя может занять 1-5 секунд.

  • Ограничения по времени. Обычно максимум 15 минут на выполнение.

  • Ограничения по памяти. Обычно до 10 ГБ (AWS Lambda).

  • Vendor lock-in. Код привязан к провайдеру.

Сравнение паттернов

Критерий Монолит Микросервисы Серверлесс
Сложность разработки Низкая Высокая Средняя
Операционная нагрузка Средняя Высокая Низкая
Масштабируемость Вертикальная Горизонтальная Автоматическая
Скорость разработки Высокая Средняя Высокая
Стоимость при низкой нагрузке Средняя Высокая Низкая
Стоимость при высокой нагрузке Низкая Средняя Высокая
Отладка Простая Сложная Средняя
Транзакции ACID Saga / eventual Eventual

Гибридные подходы

На практике редко используется чистый паттерн. Чаще встречаются гибриды:

Монолит + серверлесс для фоновых задач

Основное приложение — монолит, а фоновые задачи (отправка email, обработка изображений) — серверлесс-функции:

# Монолит: FastAPI
from fastapi import FastAPI
import httpx

app = FastAPI()

@app.post("/orders")
def create_order(order: dict):
    # Сохраняем заказ
    save_order(order)
    # Вызываем серверлесс-функцию для обработки
    httpx.post("https://api.gcp.run/notify-order", json=order)
    return {"status": "queued"}

Микросервисы + серверлесс для пиковых нагрузок

Критические сервисы — микросервисы, а пиковые задачи (отправка уведомлений при распродаже) — серверлесс:

[API Gateway]
    ├── [Orders Service] (микросервис, 24/7)
    ├── [Products Service] (микросервис, 24/7)
    ├── [Notification Lambda] (серверлесс, по событию)
    └── [Report Generator Lambda] (серверлесс, cron)

Как выбрать: практический алгоритм

  1. Начинайте с монолита. Это не компромисс — это стратегия. Большинство проектов так и остаются монолитами.

  2. Переходите к микросервисам, когда:

  3. Команда выросла до 10+ разработчиков
  4. Разные части системы обновляются с разной частотой
  5. Нагрузка на компоненты сильно различается
  6. Монолит стал слишком медленным для сборки и деплоя

  7. Используйте серверлесс для:

  8. Фоновых задач, которые не нужны в реальном времени
  9. Пиковых нагрузок, которые нельзя предсказать
  10. Webhook-обработчиков и интеграций

  11. Не делайте микросервисы «на вырост». Сложность микросервисов — это постоянные расходы. Не платите за то, что вам не нужно.

Заключение

Архитектурный паттерн — это инструмент, а не цель. Монолит не устарел, микросервисы не панацея, серверлесс не замена всему. Правильный выбор зависит от размера команды, нагрузки, бюджета и операционных возможностей.

Главное правило: начинайте с самого простого решения, которое решает вашу задачу. Усложняйте архитектуру только тогда, когда простые решения перестают работать — и только для конкретной проблемы.

Ключевые моменты:

  1. Монолит — лучший старт для большинства проектов. Простота, скорость разработки, лёгкая отладка.

  2. Микросервисы оправданы при большой команде и разной нагрузке на компоненты, но требуют инфраструктуры и экспертизы.

  3. Серверлесс идеален для фоновых задач и пиковых нагрузок — нулевая операционная нагрузка.

  4. Гибридные подходы (монолит + серверлесс) часто эффективнее чистых паттернов.

  5. Усложняйте архитектуру только при реальных проблемах, а не «на вырост».

AI-Помощник