× Install ThecoreGrid App
Tap below and select "Add to Home Screen" for full-screen experience.
B2B Engineering Insights & Architectural Teardowns

Tagged storage для multi-tenant конфигураций

Tagged storage pattern решает проблему устаревших конфигураций и перегрузки metadata service в multi-tenant системах. Разбираем, как это работает на AWS и где проходят границы компромиссов.

Проблема проявляется не сразу — до момента, когда число арендаторов (tenants) выходит за сотни, а конфигурации начинают меняться быстрее, чем живёт кэш. Классический подход с TTL упирается в противоречие: либо принимаем устаревшие данные и рискуем нарушить изоляцию или feature flags, либо агрессивно инвалидируем кэш и нагружаем metadata service. В этот момент сама служба конфигураций становится узким местом по throughput. Ситуацию усложняет разнородность данных: часть конфигураций требует высокой частоты чтения (подходит DynamoDB), другая — иерархии и версионирования (Parameter Store). Универсального хранилища здесь нет, и попытка использовать одно ведёт к избыточным затратам или деградации latency.

Решение строится вокруг tagged storage pattern. Идея проста: ключи конфигураций получают префиксы (например, tenant_config_ или param_config_), которые определяют, в какое хранилище уйдёт запрос. Это снимает необходимость выбирать «одно лучшее» хранилище и позволяет маршрутизировать данные по их access pattern. Внутри сервиса используется Strategy Pattern, который на основе ключа выбирает backend. Это компромиссное, но прагматичное решение: добавление нового хранилища не требует переписывания логики, но вводит дополнительный слой абстракции и усложняет отладку.

Архитектура опирается на несколько слоёв. На уровне входа запросы проходят через Cognito, WAF и API Gateway, затем через VPC Link попадают в ALB и далее в сервисы на ECS Fargate. Внутри сервисного слоя используется NestJS с gRPC. Это снижает накладные расходы сети и улучшает latency для service-to-service взаимодействия. Ключевой момент — tenant isolation: сервис не принимает tenantId из запроса, он извлекается из JWT. Это убирает класс атак, где клиент пытается подменить контекст арендатора.

Слой хранения реализован как multi-backend стратегия. DynamoDB использует составные ключи для изоляции и эффективных запросов. Parameter Store организован иерархически, что упрощает управление версиями. В более сложных сценариях вводится дополнительное измерение в ключе (например, service-level), что позволяет ограничивать доступ не только на уровне tenant, но и на уровне сервиса. Это важно для систем с разной зоной ответственности внутри одного арендатора.

Отдельная проблема — синхронизация конфигураций. Polling создаёт лишнюю нагрузку и задержки. Рестарты сервисов дают downtime. Здесь применяется event-driven подход: EventBridge отслеживает изменения в Parameter Store и триггерит Lambda, которая обновляет локальный кэш. Это устраняет окно устаревания и убирает необходимость polling. Конфигурации обновляются в течение секунд без прерывания пользовательских сессий.

Кэширование реализовано на нескольких уровнях. В памяти сервиса хранится metadata с ключами вида tenantId:serviceName:configKey. При этом чувствительные данные не кэшируются — они остаются в Parameter Store с шифрованием (SecureString). Это важный баланс между производительностью и безопасностью. При необходимости можно вынести кэш в Redis или Valkey, но это добавит сетевую задержку в пределах нескольких миллисекунд.

С точки зрения безопасности, изоляция обеспечивается на нескольких уровнях: JWT, ключи DynamoDB и логика сервиса. Возможен и более строгий вариант — через STS и Token Vending Machine для выдачи временных IAM-учётных данных на tenant. Это усиливает контроль (включая audit через CloudTrail), но добавляет latency и операционную сложность.

Результат такого подхода — система, которая масштабируется без явного bottleneck в metadata service и не страдает от устаревших конфигураций. При этом точных метрик улучшения не приводится, но архитектурно устраняется основной конфликт между consistency и производительностью. Цена — усложнение архитектуры и необходимость поддерживать несколько storage backend одновременно.

Tagged storage pattern не универсален. Он оправдан, когда:

  • есть разные типы конфигураций с разным access pattern
  • количество tenants растёт
  • важна строгая изоляция и быстрые обновления

В остальных случаях это может быть избыточным. Но как эволюционное улучшение для зрелых multi-tenant систем — это логичный шаг.

Читать

×

🚀 Deploy the Blocks

Controls: ← → to move, ↑ to rotate, ↓ to drop.
Mobile: use buttons below.