Проекты, где Lambda дёргает Lambda напрямую через SDK — это связанность, хрупкость и сложность отладки. Когда появляется пятнадцатый потребитель того же события, приходится обновлять каждый источник. Event-Driven архитектура на серверлес решает это: компоненты общаются через события, а не прямые вызовы. Lambda функция не знает, кто ещё подписан на результат её работы. Это обеспечивает слабую связность, независимый масштаб и возможность добавлять новых потребителей без изменения источника. Наш опыт в десятках проектов подтверждает: такой подход в 3-5 раз ускоряет внедрение новых сервисов по сравнению с монолитным связыванием, а стоимость инфраструктуры снижается на 30-50% за счёт отказа от неиспользуемых ресурсов.
Почему Event-Driven, а не прямое связывание?
Прямые вызовы Lambda из Lambda (через SDK Invoke) создают жёсткие зависимости. Если процесс оплаты дёргает сервис доставки, а через месяц нужен фрод-фильтр, приходится править код оплаты. В event-driven модели каждый сервис публикует события, а новые потребители подписываются без изменений источника. Это радикально упрощает эволюцию системы и позволяет независимо деплоить компоненты.
По данным AWS, EventBridge обрабатывает свыше 4 трлн событий в месяц, обеспечивая задержку менее 100 мс.
Сравните: при прямых вызовах отказ одного звена рушит всю цепочку. EventBridge с SQS даёт гарантию доставки и автоматические ретраи — в 10 раз надёжнее, чем ручная обработка ошибок.
Архитектура на примере e-commerce
Обработка заказа без event-driven: PlaceOrder → ValidateInventory → ProcessPayment → SendEmail → UpdateAnalytics — всё последовательно, тесно связано.
С event-driven:
[Client] → PlaceOrder Lambda
↓
EventBridge: order.created
/ | \
ValidateInv SendEmail Analytics
↓
EventBridge: inventory.reserved
↓
ProcessPayment
↓
EventBridge: payment.processed
/ \
FulfillOrder SendReceipt
Каждый сервис реагирует на события независимо. Новый сервис (например, fraud detection) подписывается на order.created без изменений существующего кода.
Как это работает на практике
AWS EventBridge: реализация
# Custom event bus + rule + target
resource "aws_cloudwatch_event_bus" "orders" {
name = "orders-bus"
}
resource "aws_cloudwatch_event_rule" "order_created" {
name = "order-created"
event_bus_name = aws_cloudwatch_event_bus.orders.name
event_pattern = jsonencode({
"detail-type": ["OrderCreated"],
"source": ["com.company.orders"]
})
}
resource "aws_cloudwatch_event_target" "process_inventory" {
rule = aws_cloudwatch_event_rule.order_created.name
event_bus_name = aws_cloudwatch_event_bus.orders.name
arn = aws_lambda_function.validate_inventory.arn
}
Публикация события из Lambda:
import boto3
import json
from datetime import datetime
events = boto3.client('events')
def publish_order_created(order: dict):
events.put_events(
Entries=[{
'EventBusName': 'orders-bus',
'Source': 'com.company.orders',
'DetailType': 'OrderCreated',
'Detail': json.dumps({
'orderId': order['id'],
'customerId': order['customer_id'],
'items': order['items'],
'totalAmount': order['total'],
'timestamp': datetime.utcnow().isoformat()
}),
'Time': datetime.utcnow()
}]
)
SQS для надёжной доставки
EventBridge + SQS = отказоустойчивая доставка с retry и dead letter queue. Используем Terraform для инфраструктуры как кода:
resource "aws_sqs_queue" "inventory_updates" {
name = "inventory-updates"
visibility_timeout_seconds = 300
redrive_policy = jsonencode({
deadLetterTargetArn = aws_sqs_queue.inventory_dlq.arn
maxReceiveCount = 3 # After 3 failures → DLQ
})
}
resource "aws_lambda_event_source_mapping" "inventory_processor" {
event_source_arn = aws_sqs_queue.inventory_updates.arn
function_name = aws_lambda_function.process_inventory.arn
batch_size = 10
function_response_types = ["ReportBatchItemFailures"]
}
ReportBatchItemFailures — только неудачные сообщения возвращаются в очередь, успешные не повторяются.
Обработчик с partial failure
def handler(event, context):
failed_message_ids = []
for record in event['Records']:
try:
process_message(json.loads(record['body']))
except Exception as e:
# Только этот record пойдёт в retry, остальные — ОК
failed_message_ids.append({'itemIdentifier': record['messageId']})
return {'batchItemFailures': failed_message_ids}
Как обеспечить идемпотентность?
В event-driven системах события могут доставляться дважды (at-least-once delivery). Каждый обработчик должен быть идемпотентным. Используем DynamoDB как таблицу обработки с ConditionExpression:
import boto3
dynamodb = boto3.resource('dynamodb')
processed_events = dynamodb.Table('processed_events')
def handler(event, context):
for record in event['Records']:
event_id = record['messageId']
# Проверить, не обработано ли событие уже
try:
processed_events.put_item(
Item={'event_id': event_id, 'ttl': int(time.time()) + 86400},
ConditionExpression='attribute_not_exists(event_id)'
)
except processed_events.meta.client.exceptions.ConditionalCheckFailedException:
continue # Already processed
process_event(record)
Процесс внедрения
Внедрение event-driven архитектуры под ключ включает этапы:
| Этап | Сроки |
|---|---|
| Проектирование event schema + шины | 2–3 дня |
| EventBridge настройка + правила маршрутизации | 2–3 дня |
| SQS + DLQ + Lambda event sources | 2–3 дня |
| Идемпотентность обработчиков | 2–4 дня |
| Distributed tracing + мониторинг | 2–3 дня |
| Интеграционное тестирование | 2–4 дня |
Все этапы могут выполняться параллельно для разных компонентов. Сроки зависят от сложности бизнес-логики и количества сервисов. Средний проект — 14 рабочих дней.
Сравнение: event-driven vs микросервисы на REST
Таблица сравнения
| Параметр | Event-Driven (AWS) | REST Микросервисы |
|---|---|---|
| Связанность | Слабая (через события) | Сильная (прямые вызовы) |
| Отказоустойчивость | Встроенные ретраи, DLQ | Ручная обработка, circuit breaker |
| Масштабирование | Независимое, per consumer | Требует синхронизации |
| Добавление нового сервиса | Подписка без изменений | Часто правка API gateway |
| Задержка | ~100 мс (EventBridge) | ~10 мс (прямой вызов) |
Мониторинг event-driven системы
Ключевые метрики:
- Event lag (SQS
ApproximateAgeOfOldestMessage) — насколько свежие события обрабатываются - DLQ depth — число событий в dead letter queue (ненулевое значение = проблема)
- Processing rate vs production rate — успевает ли система потреблять события
- End-to-end latency — время от события до результата через всю цепочку
Мы настраиваем CloudWatch alarms и дашборды, чтобы вовремя реагировать на отклонения. Опыт показывает: хороший мониторинг сокращает время реакции на инциденты в 2-3 раза.
Сколько времени занимает внедрение?
Сроки варьируются от 10 до 25 рабочих дней в зависимости от количества сервисов и сложности бизнес-логики. Оценка проекта бесплатна — пишите, мы подготовим детальный план и архитектурную схему.
Что входит в работу
Документация архитектуры и event schema, код Lambda-функций и инфраструктура как код (Terraform), настройка шин и очередей, реализация идемпотентности, мониторинг и алерты, тестовые скрипты, обучение команды. Мы даём гарантию на работоспособность решения в течение месяца после деплоя.
Закажите внедрение event-driven архитектуры — ваша система станет гибче и масштабируемее. Свяжитесь с нами для оценки вашего проекта, и мы подберём оптимальное решение.







