Casino Platform Sizing
Документация по ресурсам и масштабированию 22 микросервисов: минимальные требования, корреляция с DAU, узкие места и интерактивный калькулятор.
С чего начать
- Хочу прикинуть для своего DAU → 🧮 Калькулятор
- Хочу обзор всей платформы → Сводная таблица
- Хочу детали по конкретному сервису → Все сервисы
- Понять как считается → Методология
- Связи между сервисами → Зависимости или Граф
Топ-5 узких мест роста
| Граница | Что ломается | Решение |
|---|---|---|
| 1k → 10k DAU | Postgres connections > 200 | PgBouncer (transaction mode) |
| 10k → 100k DAU | BI/stats aggregations | ClickHouse + materialized views |
| 100k → 1M DAU | Wallet single primary | Sharding по user_id |
| 100k → 1M DAU | Auth sessions в DB | Redis-only / JWT stateless |
| T3+ (regulatory) | Risk-management 7yr retention | Партиции + S3/Glacier |
Распределение нагрузки по сервисам
| Сервис | Класс | RPS share | Кеш-хит | q/req |
|---|
Все цифры — оценка с погрешностью ±30%. Перед production обязателен нагрузочный тест.
Сгенерировано из методологии в ci-templates/docs/sizing/.
🧮 Калькулятор ресурсов
Введи DAU и параметры профиля юзера — получишь требования по RAM/CPU/Disk + DB QPS на каждый сервис.
Параметры
Итого по платформе
Per-service сайзинг
| Service | RPS peak | App RAM (GB) | App CPU | DB rd QPS | DB wr QPS | Pool | Replicas | Total RAM (GB) | Total CPU |
|---|
Сводная таблица ресурсов по всем сервисам
Применение методологии (00-methodology.md) к профилям сервисов (profiles/*.md) с распределением RPS из 10-rps-distribution.md.
Все цифры — суммарно: app + Postgres + Redis на сервис. Если сервис делит общую базу с другим — учитывай это отдельно.
Допущения:
- Включён 30% headroom для GC, шумных соседей, кратковременных пиков
- PG/Redis = standalone до 10k DAU, replica/cluster — выше
- CGO_ENABLED=1 (где есть)
- Buffer = +20% RAM на peak burst
---
Тиры архитектуры
| Тир | DAU | Pattern |
|---|---|---|
| T0 | ≤ 10 | demo, dev, smoke test |
| T1 | ≤ 1k | small operator |
| T2 | ≤ 10k | medium operator |
| T3 | ≤ 100k | large operator |
| T4 | ≤ 1M | enterprise / multi-region |
---
Per-Service Sizing — суммарно (app + DB + Redis)
casino-core-service (medium)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.3 | 80 MB | 0.1 | 256 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 8 | 200 MB | 0.3 | 1 GB | 1 | 5 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 80 | 700 MB | 1.5 | 2 GB | 2 | 30 GB | 512 MB | 3.2 GB | 3.5 |
| 100k | 800 | 4 GB ×2 | 4 | 8 GB | 4 | 300 GB | 4 GB | 20 GB | 12 |
| 1M | 8000 | 16 GB ×4 | 16 | 32 GB ×2 | 16 | 3 TB | 16 GB ×2 | 128 GB | 80 |
casino-game-processing-service (heavy — orchestrator)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.3 | 100 MB | 0.2 | 256 MB | 0.5 | 1 GB | 64 MB | 0.5 GB | 0.7 |
| 1k | 6.4 | 250 MB | 0.5 | 1 GB | 1 | 8 GB | 256 MB | 1.5 GB | 1.5 |
| 10k | 64 | 1 GB | 2 | 4 GB | 4 | 60 GB | 1 GB | 6 GB | 6 |
| 100k | 640 | 4 GB ×3 | 9 | 16 GB | 8 | 600 GB | 4 GB | 32 GB | 18 |
| 1M | 6400 | 16 GB ×6 | 36 | 64 GB ×2 (sharded) | 32 | 6 TB | 16 GB ×2 | 224 GB | 150 |
casino-wallet-service (heavy — financial critical)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.5 | 100 MB | 0.2 | 512 MB | 0.5 | 1 GB | 64 MB | 0.7 GB | 0.7 |
| 1k | 5 | 300 MB | 0.5 | 2 GB | 1 | 10 GB | 256 MB | 2.5 GB | 1.5 |
| 10k | 48 | 1 GB | 2 | 8 GB | 4 | 100 GB | 1 GB | 10 GB | 6 |
| 100k | 480 | 4 GB ×3 | 9 | 32 GB primary + 32 GB replica | 16 | 1 TB | 8 GB | 96 GB | 40 |
| 1M | 4800 | 16 GB ×6 | 36 | 128 GB sharded ×2 + replicas | 64 | 10 TB | 32 GB cluster | 440 GB | 220 |
casino-auth-service (heavy — token validation)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.16 | 80 MB | 0.1 | 256 MB | 0.5 | 0.5 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 1.6 | 200 MB | 0.3 | 1 GB | 1 | 2 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 16 | 600 MB | 1 | 2 GB | 2 | 20 GB | 1 GB | 3.6 GB | 3 |
| 100k | 160 | 2 GB ×2 | 4 | 8 GB primary + replica | 4 | 200 GB | 4 GB | 18 GB | 12 |
| 1M | 1600 | 8 GB ×4 | 16 | 32 GB primary + 2 replicas | 16 | 2 TB | 16 GB cluster | 96 GB | 64 |
casino-bonuses-service (heavy — every bet)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.32 | 100 MB | 0.2 | 512 MB | 0.5 | 1 GB | 128 MB | 0.7 GB | 0.7 |
| 1k | 3.2 | 300 MB | 0.5 | 2 GB | 2 | 10 GB | 512 MB | 3 GB | 2.5 |
| 10k | 32 | 1.5 GB | 2 | 8 GB | 4 | 100 GB | 2 GB | 12 GB | 6 |
| 100k | 320 | 4 GB ×3 | 8 | 32 GB | 8 | 1 TB | 8 GB | 52 GB | 24 |
| 1M | 3200 | 16 GB ×4 | 32 | 64 GB primary + replica | 32 | 10 TB | 32 GB cluster | 224 GB | 130 |
casino-payment-service (heavy — PSP orchestrator)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.03 | 80 MB | 0.1 | 256 MB | 0.5 | 0.5 GB | 64 MB | 0.4 GB | 0.7 |
| 1k | 0.3 | 200 MB | 0.3 | 1 GB | 1 | 5 GB | 256 MB | 1.5 GB | 1.5 |
| 10k | 3 | 500 MB | 0.7 | 2 GB | 2 | 50 GB | 512 MB | 3 GB | 2.7 |
| 100k | 32 | 2 GB ×2 | 3 | 8 GB | 4 | 500 GB | 2 GB | 16 GB | 9 |
| 1M | 320 | 4 GB ×3 | 12 | 32 GB primary + replica | 16 | 5 TB | 8 GB | 80 GB | 45 |
casino-bi-service (analytics — write-heavy + slow reads)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0 | 100 MB | 0.1 | 1 GB | 1 | 5 GB | 64 MB | 1.2 GB | 1.2 |
| 1k | 0 | 250 MB | 0.3 | 4 GB | 2 | 50 GB | 128 MB | 4.5 GB | 2.5 |
| 10k | 0 | 1 GB | 1 | 16 GB | 4 | 500 GB | 256 MB | 18 GB | 6 |
| 100k | 0 | 2 GB | 2 | 64 GB | 16 | 5 TB | 1 GB | 70 GB | 20 |
| 1M | 0 | 4 GB | 4 | → ClickHouse: 64 GB / 32 cores / 50 TB | — | — | 4 GB | 120 GB | 40 |
BI > 10k DAU — мигрировать на ClickHouse. Postgres перестаёт справляться с aggregation queries.
casino-stats-service (write-heavy, аналог BI на меньшем масштабе)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.16 | 80 MB | 0.1 | 256 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 1.6 | 200 MB | 0.3 | 2 GB | 1 | 20 GB | 256 MB | 2.5 GB | 1.5 |
| 10k | 16 | 600 MB | 1 | 8 GB | 4 | 200 GB | 512 MB | 9 GB | 5 |
| 100k | 160 | 2 GB ×2 | 4 | 32 GB | 8 | 2 TB | 2 GB | 40 GB | 15 |
| 1M | 1600 | 8 GB ×3 | 12 | → ClickHouse: 32 GB / 16 cores / 20 TB | — | — | 8 GB | 80 GB | 35 |
casino-achievement-service (write-heavy через Kafka)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.06 | 80 MB | 0.1 | 256 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 0.6 | 200 MB | 0.3 | 1 GB | 1 | 10 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 6 | 600 MB | 1 | 4 GB | 2 | 100 GB | 512 MB | 5 GB | 3 |
| 100k | 64 | 2 GB ×2 | 3 | 16 GB | 4 | 1 TB | 2 GB | 22 GB | 9 |
| 1M | 640 | 8 GB ×3 | 9 | 64 GB partitioned | 16 | 5 TB partitioned | 8 GB | 96 GB | 35 |
casino-back-office-service (admin only)
Особенность: RPS почти не растёт от DAU юзеров — только от количества админов (~50-200 на крупного клиента).
| DAU | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| любой ≤ 100k | 256 MB | 0.5 | 1 GB | 1 | 50 GB (audit_log) | 128 MB | 1.4 GB | 1.5 |
| 1M | 512 MB | 1 | 4 GB | 2 | 200 GB | 256 MB | 5 GB | 3 |
casino-config-service (read-heavy, агрессивный кеш)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.01 | 50 MB | 0.05 | 256 MB | 0.5 | 0.1 GB | 32 MB | 0.3 GB | 0.6 |
| 1k | 0.1 | 100 MB | 0.1 | 256 MB | 0.5 | 0.5 GB | 64 MB | 0.5 GB | 0.6 |
| 10k | 1 | 200 MB | 0.2 | 512 MB | 0.5 | 1 GB | 128 MB | 0.9 GB | 0.7 |
| 100k | 10 | 400 MB | 0.5 | 1 GB | 1 | 5 GB | 256 MB | 1.7 GB | 1.5 |
| 1M | 96 | 1 GB ×2 | 2 | 2 GB | 1 | 10 GB | 1 GB | 5 GB | 3 |
casino-jackpot-service (atomic counters, kafka consumer)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.10 | 80 MB | 0.1 | 256 MB | 0.5 | 0.5 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 1 | 150 MB | 0.2 | 512 MB | 0.5 | 2 GB | 128 MB | 0.8 GB | 0.7 |
| 10k | 10 | 400 MB | 0.5 | 1 GB | 1 | 20 GB | 256 MB | 1.7 GB | 1.5 |
| 100k | 100 | 1 GB ×2 | 2 | 4 GB | 2 | 200 GB | 1 GB | 8 GB | 4 |
| 1M | 960 | 4 GB ×3 | 8 | 16 GB primary + replica | 8 | 2 TB | 4 GB | 40 GB | 20 |
casino-tournament-service (leaderboards via Redis)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.06 | 80 MB | 0.1 | 256 MB | 0.5 | 0.5 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 0.6 | 150 MB | 0.2 | 512 MB | 0.5 | 2 GB | 256 MB | 0.9 GB | 0.7 |
| 10k | 6 | 400 MB | 0.5 | 1 GB | 1 | 20 GB | 1 GB | 2.5 GB | 1.5 |
| 100k | 64 | 1 GB ×2 | 2 | 4 GB | 2 | 200 GB | 4 GB | 14 GB | 5 |
| 1M | 640 | 4 GB ×3 | 8 | 16 GB | 8 | 2 TB | 16 GB | 64 GB | 24 |
casino-segmentation-service (5-second recalc loop)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.06 | 80 MB | 0.1 | 256 MB | 0.5 | 0.1 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 0.6 | 150 MB | 0.2 | 512 MB | 0.5 | 1 GB | 128 MB | 0.8 GB | 0.7 |
| 10k | 6 | 400 MB | 0.7 | 2 GB | 2 | 10 GB | 256 MB | 2.7 GB | 2.7 |
| 100k | 64 | 1.5 GB | 2 | 8 GB | 4 | 100 GB | 1 GB | 11 GB | 6 |
| 1M | 640 | 4 GB ×2 | 8 | 32 GB | 16 | 1 TB | 4 GB | 44 GB | 24 |
casino-risk-management-service (sync withdraw path)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.06 | 80 MB | 0.1 | 256 MB | 0.5 | 0.5 GB | 64 MB | 0.4 GB | 0.6 |
| 1k | 0.6 | 200 MB | 0.3 | 1 GB | 1 | 5 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 6 | 600 MB | 1 | 4 GB | 2 | 50 GB | 512 MB | 5 GB | 3 |
| 100k | 64 | 2 GB ×2 | 3 | 16 GB | 4 | 500 GB | 2 GB | 22 GB | 9 |
| 1M | 640 | 8 GB ×3 | 9 | 64 GB (partitioned, 7yr retention) | 16 | 5 TB | 8 GB | 96 GB | 35 |
casino-sportsbook-service (Digitain webhook)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|---|
| 10 | 0.13 | 80 MB | 0.1 | 256 MB | 0.5 | 0.5 GB | — | 0.3 GB | 0.6 |
| 1k | 1.3 | 200 MB | 0.3 | 1 GB | 1 | 5 GB | — | 1.2 GB | 1.3 |
| 10k | 13 | 600 MB | 1 | 4 GB | 2 | 50 GB | 256 MB (нужно добавить) | 5 GB | 3 |
| 100k | 130 | 2 GB ×2 | 3 | 16 GB | 4 | 500 GB | 1 GB | 20 GB | 9 |
| 1M | 1280 | 8 GB ×3 | 12 | 64 GB primary + replica | 16 | 5 TB | 4 GB | 88 GB | 45 |
casino-balancer (geo-redirect)
| DAU | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|
| 10 | 80 MB | 0.1 | 256 MB | 0.3 | 0.1 GB | 0.3 GB | 0.4 |
| 1k | 150 MB | 0.2 | 256 MB | 0.3 | 0.5 GB | 0.4 GB | 0.5 |
| 10k | 300 MB | 0.5 | 512 MB | 0.5 | 2 GB | 0.8 GB | 1 |
| 100k | 1 GB | 2 | 1 GB | 1 | 20 GB | 2 GB | 3 |
| 1M | 4 GB ×2 | 8 | 4 GB | 2 | 200 GB | 12 GB | 10 |
Это лишь redirect-сервис, использует in-memory GeoIP — RPS легко масштабируется горизонтально.
casino-store-service (in-app store)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 0.06 | 60 MB | 0.05 | 256 MB | 0.3 | 32 MB | 0.3 GB | 0.4 |
| 1k | 0.6 | 100 MB | 0.1 | 512 MB | 0.5 | 64 MB | 0.7 GB | 0.6 |
| 10k | 6 | 250 MB | 0.3 | 1 GB | 1 | 128 MB | 1.4 GB | 1.3 |
| 100k | 64 | 1 GB | 1 | 4 GB | 2 | 512 MB | 6 GB | 3 |
| 1M | 640 | 4 GB ×2 | 6 | 16 GB | 4 | 2 GB | 26 GB | 10 |
casino-partner-service (affiliate, polling-based)
| DAU | RPS peak | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 0.02 | 60 MB | 0.05 | 256 MB | 0.3 | 0.5 GB | 0.3 GB | 0.4 |
| 1k | 0.16 | 100 MB | 0.1 | 512 MB | 0.5 | 5 GB | 0.6 GB | 0.6 |
| 10k | 1.6 | 250 MB | 0.3 | 1 GB | 1 | 50 GB | 1.3 GB | 1.3 |
| 100k | 16 | 1 GB | 1 | 4 GB | 2 | 500 GB | 5 GB | 3 |
| 1M | 160 | 4 GB ×2 | 4 | 16 GB | 8 | 5 TB (нужна архивация) | 24 GB | 12 |
casino-referral-service
| DAU | App RAM | App CPU | PG RAM | PG CPU | PG Disk/yr | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|
| 10 | 60 MB | 0.05 | 256 MB | 0.3 | 0.1 GB | 0.3 GB | 0.4 |
| 1k | 100 MB | 0.1 | 256 MB | 0.3 | 0.5 GB | 0.4 GB | 0.4 |
| 10k | 200 MB | 0.2 | 512 MB | 0.5 | 5 GB | 0.7 GB | 0.7 |
| 100k | 800 MB | 1 | 2 GB | 1 | 50 GB | 3 GB | 2 |
| 1M | 3 GB | 4 | 8 GB | 2 | 500 GB | 11 GB | 6 |
casino-notifications-service (multi-channel fan-out)
Heavy: 4 Kafka consumer groups, 6 каналов, sync вызовы провайдеров.
| DAU | App RAM | App CPU | PG RAM | PG CPU | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|
| 10 | 100 MB | 0.1 | 256 MB | 0.5 | 64 MB | 0.4 GB | 0.6 |
| 1k | 200 MB | 0.3 | 512 MB | 0.5 | 128 MB | 0.8 GB | 0.8 |
| 10k | 600 MB | 1 | 1 GB | 1 | 256 MB | 1.9 GB | 2 |
| 100k | 2 GB ×2 | 3 | 4 GB | 2 | 1 GB | 9 GB | 5 |
| 1M | 8 GB ×3 | 12 | 16 GB | 4 | 4 GB | 44 GB | 16 |
---
Итого по платформе (без избыточности — single instance)
| DAU | Сумма RAM | Сумма CPU | Disk/год | Архитектура |
|---|---|---|---|---|
| 10 | ~10 GB | ~10 cores | ~10 GB | T0 — одна VM (8 vCPU / 16 GB / 100 GB) |
| 1k | ~25 GB | ~22 cores | ~50 GB | T1 — одна VM (16 vCPU / 32 GB / 250 GB) или 2 VM (app + infra) |
| 10k | ~110 GB | ~63 cores | ~600 GB | T2 — 3-5 VM (8 vCPU / 32 GB), отдельно DB и Redis |
| 100k | ~470 GB | ~200 cores | ~7 TB | T3 — 10-20 VM или K8s, replicas, PgBouncer обязателен |
| 1M | ~2 TB | ~1000 cores | ~70 TB | T4 — Kubernetes, шардинг, ClickHouse для аналитики, multi-AZ |
---
С учётом репликации и HA
Множители для T2+:
- PG: ×2 (primary + replica) или ×3 (primary + 2 replica)
- App: ×N подов для HA (минимум ×2)
- Redis: ×2 (master + replica) или ×6 (cluster 3+3)
- Kafka: 3 брокера (для T3+)
Финальный множитель к "сумме single instance": ~2.5× для T3, ~4× для T4.
| DAU | Single instance | + HA | + Резерв 30% | **Итого нужно купить** |
|---|---|---|---|---|
| 10k | 110 GB / 63 cpu | 220 GB / 110 cpu | 285 GB / 145 cpu | 5-7 VM × 64 GB / 32 cpu |
| 100k | 470 GB / 200 cpu | 1.2 TB / 500 cpu | 1.5 TB / 650 cpu | 15-25 VM × 64 GB / 32 cpu |
| 1M | 2 TB / 1000 cpu | 6 TB / 2.5k cpu | 8 TB / 3.3k cpu | K8s ~80 nodes × 96 GB / 48 cpu |
---
Запросы к БД и Redis
Самая важная метрика для PG — DB QPS = HTTP RPS × queries_per_request. Часть запросов идёт мимо HTTP — через Kafka consumer'ов.
DB read QPS платформы (после кеша)
| DAU | Total HTTP RPS | DB read QPS | DB write QPS | Redis QPS |
|---|---|---|---|---|
| 10 | 0.3 | 0.2 | 0.4 | 0.4 |
| 100 | 3.2 | 2.6 | 4.3 | 4 |
| 1k | 32 | 26 | 43 | 40 |
| 10k | 320 | 256 | 425 | 405 |
| 100k | 3 200 | 2 556 | 4 254 | 4 050 |
| 1M | 32 000 | 25 562 | 42 535 | 40 500 |
Write QPS преобладает над read в этой платформе — нагрузка финансово-транзакционная (wallet, bonuses, stats события). Это разворачивает обычные предположения "80% read / 20% write" в casino.
Pool sum (суммарно по всем сервисам)
| DAU | Pool sum | Действие |
|---|---|---|
| 10 | 210 | PgBouncer обязателен (минимум 10 conn × 21 сервис) |
| 1k | 210 | PgBouncer обязателен |
| 10k | 210 | PgBouncer обязателен |
| 100k | 285 | PgBouncer обязателен |
| 1M | 1 422 | PgBouncer + 1 на pool на app pod |
Топ-3 сервиса по connections @ 1M DAU:
- game-processing — 519 connections
- wallet — 389 connections
- bonuses — 138 connections
DB QPS по сервисам @ 100k DAU
| Сервис | RPS | Read QPS | Write QPS | Pool | Доминирующий запрос |
|---|---|---|---|---|---|
| game-processing | 640 | 1 024 | 1 282 | 52 | Multi-table session updates |
| wallet | 480 | 288 | 1 441 | 39 | INSERT tx + UPDATE balance + SELECT FOR UPDATE |
| bonuses | 320 | 288 | 323 | 14 | Wagering progress + active bonuses |
| sportsbook | 128 | 269 | 257 | 10 | Webhook → multi-table |
| core | 800 | 384 | 80 | 10 | CMS list+detail (80% cached) |
| stats | 160 | 0 | 199 | 10 | Event ingest (Kafka) |
| achievement | 64 | 38 | 133 | 10 | Progress check+update |
| jackpot | 96 | 19 | 98 | 10 | Pool counter |
| auth | 160 | 12 | 11 | 10 | Token/session lookup (95% cached) |
Что переходит грань "PG не справится"
| Граница | Что происходит | Решение |
|---|---|---|
| ~150 conn total | PG default max_connections issue | PgBouncer transaction mode |
| game-proc 50+ conn | Single primary не успевает | Read replica для не-критичных reads |
| wallet 100+ conn | Lock contention на balance row |
Sharding по user_id |
| bi 100+ heavy QPS | Aggregation queries блокируют writes | ClickHouse + materialized views |
| 1k+ writes/sec в одну таблицу | WAL throughput | SSD NVMe + WAL на отдельный диск |
---
Топ-5 расходных статей
- PostgreSQL master (wallet, bonuses, bi) — самый дорогой компонент
- Kafka cluster (3+ брокера, 30 топиков) — стабильно ~10% стоимости
- Redis (jackpot counters, leaderboards, session, cache) — растёт линейно
- ClickHouse / analytics DB — обязателен для T3+ (вместо PG для bi/stats)
- Egress traffic — для T4 значимая статья (CDN сильно помогает)
---
Что точно ЛОМАЕТСЯ при росте
| DAU | Что ломается | Как фиксить |
|---|---|---|
| 1k → 10k | Postgres connections > 200 | PgBouncer (transaction pooling) |
| 10k → 100k | bi/stats Postgres aggregations | ClickHouse, materialized views |
| 100k → 1M | wallet single primary (write contention) | Sharding по user_id, async writes |
| 100k → 1M | Kafka topic throughput (game-action) | Партиции 32+, отдельный кластер для analytics |
| 100k → 1M | auth Postgres sessions | Redis-only sessions, JWT stateless |
| 100k → 1M | risk-management retention (5-7 лет) | Партиционирование + холодное хранение (S3/Glacier) |
Методология расчёта ресурсов
Этот документ описывает формулы и допущения, по которым считаются ресурсы для каждого сервиса (SIZING.md в репо сервиса) и для всей платформы (90-summary.md).
---
Профиль пользователя (casino)
| Метрика | Значение | Комментарий |
|---|---|---|
| CCU / DAU | 8% | Concurrent users / Daily active users — типичное значение для casino, slot-heavy |
| Сессий на DAU/день | 2.5 | Среднее число логинов в день |
| Длина сессии | 18 мин | Среднее время онлайн |
| Действий в минуту (онлайн) | 8 | Спин/клик/ставка/просмотр баланса (peak — 12) |
| Депозитов на DAU/день | 0.15 | 15% юзеров делают депозит ежедневно |
| Выплат на DAU/день | 0.08 | 8% юзеров делают вывод ежедневно |
| Турниров активных | 0.3 | Доля юзеров в турнирах |
| Бонусов активных на юзера | 1.2 | Среднее число активных бонусов |
| Чат сообщений / онлайн / мин | 0.5 | Активность в чате |
| Peak coefficient | 3.0× | Часовой пик к среднесуточному |
Перевод DAU → RPS
RPS_avg = CCU × actions_per_minute / 60
= (DAU × 0.08) × 8 / 60
≈ DAU × 0.0107
RPS_peak = RPS_avg × 3.0
≈ DAU × 0.032
Таблица RPS по тирам:
| DAU | CCU | RPS avg | RPS peak |
|---|---|---|---|
| 10 | 1 | 0.1 | 0.3 |
| 100 | 8 | 1.1 | 3.2 |
| 1k | 80 | 11 | 32 |
| 10k | 800 | 107 | 320 |
| 100k | 8 000 | 1 067 | 3 200 |
| 1M | 80 000 | 10 670 | 32 000 |
Распределение RPS по сервисам (средние коэффициенты по индустрии):
| Сервис | Доля RPS | Обоснование |
|---|---|---|
| auth | 5% | Только логин/refresh — кэшируется |
| core | 25% | CMS, баннеры, чат — каждое открытие |
| game-processing | 20% | Запуск игры, состояние |
| wallet | 15% | Каждый спин трогает баланс |
| bonuses | 10% | Проверка активных бонусов |
| stats | 5% | Сохранение событий |
| остальные 16 | 20% | Делятся пропорционально |
---
Сайзинг Go-сервиса
Базовая модель
Memory = idle_baseline + per_connection × concurrent_conns + per_RPS × RPS
CPU = idle_baseline + per_RPS × RPS / efficiency_per_core
Числа по умолчанию (Go 1.25+, Gin/chi, sqlx/pgx)
| Параметр | Light service | Medium | Heavy |
|---|---|---|---|
idle_RAM (MB) |
40 | 80 | 150 |
RAM_per_concurrent_conn (KB) |
20 | 40 | 80 |
RAM_per_RPS (MB) |
0.5 | 1 | 2 |
idle_CPU |
0.05 | 0.1 | 0.2 |
RPS_per_core (sustained) |
2000 | 800 | 250 |
Что классифицирует тяжесть:
- Light: простой CRUD, мало join'ов, мало бизнес-логики (≤ 30 routes, ≤ 15k LoC)
- Medium: умеренные join'ы, кеш, валидация, события Kafka (30-150 routes, 15-50k LoC)
- Heavy: сложная бизнес-логика, много join'ов, агрегаты, JSONB, тяжёлый Kafka (>150 routes, >50k LoC)
Концурентность
concurrent_conns = RPS_peak × avg_latency_seconds × safety_factor
Где:
avg_latency= 50ms (light) / 100ms (medium) / 200ms (heavy)safety_factor= 2.0
---
Запросы к БД (Queries Per Request)
Самая важная метрика для сайзинга PG — это DB QPS = RPS × queries_per_request, а не просто HTTP RPS.
Таблица queries_per_request по типам сервисов
| Тип операции | SELECT | INSERT/UPDATE | SELECT FOR UPDATE | Avg latency | Пример |
|---|---|---|---|---|---|
| Просто кеш-чтение | 1 | 0 | 0 | 1-3ms | config get |
| CRUD list | 2-3 | 0 | 0 | 3-8ms | core list news |
| CRUD detail+children | 3-5 | 0 | 0 | 5-15ms | core get story+media |
| Простая запись | 0 | 1-2 | 0 | 5-10ms | stats event ingestion |
| Запись с проверкой | 1-2 | 1-2 | 0 | 8-15ms | bonus eligibility+grant |
| Финансовая транзакция | 1-2 | 2-4 | 1 | 10-30ms | wallet debit |
| Сложная аналитика | 1 (heavy) | 0 | 0 | 100-2000ms | bi reports |
Профиль queries_per_request по сервису
| Сервис | Avg q/req | DB read | DB write | Redis q/req | Кеш hit % | Доминирующий запрос |
|---|---|---|---|---|---|---|
| auth | 1.5 | 1.5 | 0 | 1 | 95% | session lookup (cache→DB miss) |
| core | 2.5 | 2.4 | 0.1 | 0.5 | 80% | CMS list/detail с join media |
| game-processing | 6 | 4 | 2 | 1 | 60% | game session state + multi-update |
| wallet | 5 | 2 | 3 | 1 | 70% | balance read + tx insert + audit |
| bonuses | 4 | 3 | 1 | 2 | 70% | active bonus + wagering update |
| payment | 4 | 2 | 2 | 0.5 | 30% | order lookup + tx insert + idempotency |
| stats | 1.2 | 0 | 1.2 | 0 | — | event ingest (Kafka driven) |
| bi | 0.5 | 0.5 (HEAVY) | 0 | 0.1 | 20% | aggregation queries |
| achievement | 3 | 1 | 2 | 0.5 | 40% | progress check+update |
| back-office | 4 | 4 | 0 | 1 | 90% | report queries (read replica) |
| config | 0.05 | 0.05 | 0 | 1 | 99%+ | почти всё из кеша |
| jackpot | 2 | 1 | 1 | 1 | 80% | pool check + INCR (или Redis) |
| tournament | 2.5 | 1.5 | 1 | 2 | 90% | leaderboard ZSET + DB rank persist |
| segmentation | 3 | 2 | 1 | 0.5 | 70% | segment match + recalc |
| risk-management | 3 | 2 | 1 | 1 | 80% | scoring lookup + alert insert |
| sportsbook | 5 | 3 | 2 | 0.2 | 30% | webhook → multi-table update |
| balancer | 1 | 1 | 0 | 0 | — | domain lookup (часто из памяти) |
| store | 4 | 2 | 2 | 0.5 | 60% | catalog + purchase tx |
| partner | 2 | 1.5 | 0.5 | 0.2 | 50% | tracking insert + lookup |
| referral | 2 | 1.5 | 0.5 | 0 | 0% | link lookup + insert |
| notifications | 2 | 1 | 1 | 1 | 70% | template fetch + log insert |
Расчёт DB QPS
DB_QPS_peak = RPS_peak × queries_per_request × (1 - cache_hit_rate)
# с разбивкой:
DB_read_QPS = RPS_peak × q_read × (1 - cache_hit_rate)
DB_write_QPS = RPS_peak × q_write × 1.0 # writes не кешируются
Примечание о Kafka consumers: многие сервисы (stats, achievement, bi, bonuses, segmentation, risk-management) делают БОЛЬШЕ записей через Kafka consumers, чем через HTTP. Для них DB write QPS считается отдельно: events_per_second × q_write_per_event.
Готовая таблица DB QPS пиковых для топ-сервисов
| Сервис | 1k DAU | 10k DAU | 100k DAU | 1M DAU |
|---|---|---|---|---|
| wallet (5 q/r, 70% cache) | 7 QPS | 72 QPS | 720 QPS | 7 200 QPS |
| bonuses (4 q/r, 70% cache) | 4 QPS | 38 QPS | 380 QPS | 3 800 QPS |
| wallet writes (3 w/r) | 14 wQPS | 144 wQPS | 1 440 wQPS | 14 400 wQPS |
| game-processing (6 q/r, 60%) | 15 QPS | 154 QPS | 1 536 QPS | 15 360 QPS |
| auth (1.5 q/r, 95% cache) | 0.1 QPS | 1.2 QPS | 12 QPS | 120 QPS |
| stats (Kafka writes) | ~50 wQPS | ~500 wQPS | ~5k wQPS | ~50k wQPS |
| bi (heavy aggs, low rate) | 1 QPS | 10 QPS | 100 QPS | 1k QPS (но 100ms+ each) |
Connection Pool Sizing
pool_size = MAX(10, CEIL(DB_QPS × avg_query_latency × safety))
С safety = 1.5 и avg_query_latency:
- light read = 5ms
- write = 10ms
- SELECT FOR UPDATE = 20ms
- aggregation = 200ms
Минимум pool на сервис = 10, иначе burst заблокирует все коннекты.
| Сервис | DAU 10k | DAU 100k | DAU 1M |
|---|---|---|---|
| auth | 10 (min) | 10 | 20 |
| core | 10 (min) | 25 | 100 |
| wallet | 25 | 100 | 500 (sharded) |
| bonuses | 15 | 60 | 300 |
| game-processing | 25 | 150 | 800 |
| bi | 10 (heavy q) | 25 (heavy q) | 50 (отдельный read pool) |
| TOTAL ALL services | ~150 | ~600 | ~3000+ |
Critical: PGmax_connections= 200 по умолчанию. После~150 conns— обязательно PgBouncer вtransactionmode (даёт 10-50× connections без роста реальных PG worker'ов).
Redis ops/sec
Redis_QPS = RPS_peak × redis_ops_per_request
Redis легко держит 100k+ QPS на одном инстансе для мелких ключей. Узкое место — сеть и сериализация.
| DAU | Redis QPS (платформа) | Архитектура |
|---|---|---|
| 1k | ~50 | 1 instance |
| 10k | ~500 | 1 instance |
| 100k | ~5k | 1 instance с replica |
| 1M | ~50k | Cluster или partitioning по namespace (session/cache/queue/leaderboard отдельно) |
---
Сайзинг PostgreSQL
Базовая модель
RAM_pg = shared_buffers + work_mem × max_connections × concurrent_queries_ratio + WAL + OS_cache
shared_buffers = 25% от total RAM
effective_cache_size = 50-75% от total RAM
work_mem = 4-16 MB (зависит от запросов)
max_connections = max(20, ceil(RPS_peak × 1.2 × num_services_per_db))
Сайзинг на основании юзеров
| DAU | shared_buffers | work_mem | total RAM | CPU | Disk (год) |
|---|---|---|---|---|---|
| 10 | 64 MB | 4 MB | 256 MB | 0.5 | 1 GB |
| 100 | 128 MB | 4 MB | 512 MB | 1 | 2 GB |
| 1k | 256 MB | 4 MB | 1 GB | 1 | 5 GB |
| 10k | 512 MB | 8 MB | 2 GB | 2 | 30 GB |
| 100k | 2 GB | 8 MB | 8 GB | 4 | 300 GB |
| 1M | 16 GB | 16 MB | 64 GB | 16 | 3 TB (с шардингом) |
Storage
Storage_GB = (rows_per_user_per_day × avg_row_KB × DAU × retention_days) / 1024 / 1024 + indexes_overhead (~30%)
Типичные ставки записи:
- transactions — 50 строк / DAU / день (спины + депозиты + бонусы)
- bets — 200 строк / DAU / день
- events (analytics) — 500 строк / DAU / день (часто переносится в ClickHouse)
- audit_log — 30 строк / DAU / день
Connections
max_connections = N_services × pool_size_per_service
Типично pool = 10-25 на сервис. При 22 сервисах × 25 = до 550 коннектов.
Если коннектов > 200 — обязательно ставить PgBouncer (transaction pooling).
---
Сайзинг Redis
Базовая модель
RAM_redis = baseline (5 MB) + sum(cached_keys × avg_size) + replication_buffer (10%)
Что обычно кешируется
| Тип кеша | Ключ | Размер | TTL | Хит-рейт |
|---|---|---|---|---|
| Session | session:{userId} |
2 KB | 24h | 95% |
| User profile | user:{userId} |
3 KB | 1h | 90% |
| Wallet balance | wallet:{userId} |
0.5 KB | 30s | 80% |
| Game catalog | games:list |
200 KB | 5min | 99% |
| Bonus active | bonus:user:{id} |
1 KB | 5min | 70% |
| Rate limiter | ratelimit:{ip}:{path} |
0.1 KB | 1min | — |
Сайзинг по DAU
| DAU | Redis RAM | CPU | Сценарий |
|---|---|---|---|
| 10 | 64 MB | 0.1 | один процесс |
| 100 | 128 MB | 0.2 | один процесс |
| 1k | 256 MB | 0.3 | один процесс |
| 10k | 1 GB | 0.5 | master + replica |
| 100k | 4 GB | 2 | master + 2 replicas |
| 1M | 16 GB | 4 | Cluster (3 master + 3 replica), либо 2-3 разные инстансы (session/cache/queue) |
---
Сайзинг Kafka
Производство для casino:
- 1 спин = 2-3 события (bet placed, balance changed, stats event)
- 1 депозит = 5-7 событий (incl. risk, bonus check, audit)
- avg event size = 1.5 KB
Kafka_throughput_msg_s = RPS_peak × events_per_request (avg 2.5)
Kafka_storage_GB_day = msg_per_sec × avg_event_KB × 86400 × replication / 1024 / 1024
| DAU | msg/s peak | Disk/день (RF=3, retention=7d) | RAM | CPU |
|---|---|---|---|---|
| 1k | 80 | ~50 MB | 1 GB | 0.5 |
| 10k | 800 | ~500 MB | 2 GB | 1 |
| 100k | 8k | ~5 GB | 8 GB | 4 |
| 1M | 80k | ~50 GB | 32 GB | 16 |
---
Дисковая подсистема
| DAU | IOPS sustained | IOPS peak | Throughput | Тип |
|---|---|---|---|---|
| ≤ 1k | 100 | 500 | 50 MB/s | SATA SSD |
| ≤ 10k | 1k | 5k | 250 MB/s | NVMe |
| ≤ 100k | 5k | 20k | 1 GB/s | NVMe RAID10 |
| ≤ 1M | 20k | 100k | 4 GB/s | NVMe Cluster + EBS gp3/io2 |
---
Сетевые требования
egress_Mbps = RPS_peak × avg_response_KB × 8 / 1024
При avg_response = 5 KB:
| DAU | RPS peak | Egress |
|---|---|---|
| 1k | 32 | 1.3 Mbps |
| 10k | 320 | 13 Mbps |
| 100k | 3 200 | 130 Mbps |
| 1M | 32 000 | 1.3 Gbps |
---
Шкала тиров (для целевого SLA)
| Тир | DAU | Архитектура |
|---|---|---|
| T0 — dev/demo | ≤ 10 | Single VM: всё в одном compose, без репликации |
| T1 — small client | ≤ 1k | Single VM, но Postgres+Redis на отдельных процессах. Daily backup |
| T2 — medium client | ≤ 10k | 2-3 VM: app, db, cache. Replica для PG. Backup hourly |
| T3 — large client | ≤ 100k | 5-10 VM: app cluster, PG primary+2 replicas, Redis HA, Kafka cluster |
| T4 — enterprise | ≤ 1M | Kubernetes / autoscaling. Sharded DB. Multi-region. PgBouncer. CDN |
---
Допущения и ограничения
- CGO_ENABLED=1 в большинстве сервисов — overhead ~5-10% RAM против чистого Go
- JSONB-поля в PostgreSQL увеличивают I/O — учтено в "Heavy" категории
- Без шардинга PG до 100k DAU; для 1M — обязательно шардирование
transactions,bets - Replication factor: для T3+ Postgres = streaming replication; для T4 — synchronous replication между регионами
- Cold start: после рестарта сервис прогревается 30-60 сек, в это время CPU x2 от sustained
- GC pressure в Go: при больших аллокациях RAM =
live_set × 2для нормальной работы GOGC=100
---
Источники чисел
- Industry benchmarks: TechEmpower (Gin), pgbench, redis-benchmark
- Casino-specific: GLI/iGaming reports о среднем поведении игрока
- Internal: anonymized наблюдения за реальной нагрузкой Bethub
Распределение RPS по сервисам
Используется для перевода общего DAU → RPS на каждый сервис.
Веса по сервисам
| Сервис | RPS share | Per-action | Notes |
|---|---|---|---|
| auth | 5% | 0.5/min/CCU | login + refresh + token validate (cached) |
| core | 25% | 2.5/min/CCU | CMS, chat, banners, news, FAQ — открытие любой страницы |
| game-processing | 20% | 2/min/CCU | spin, game launch, session state |
| wallet | 15% | 1.5/min/CCU | balance check на каждом spin + tx |
| bonuses | 10% | 1/min/CCU | wagering progress, eligibility |
| stats | 5% | 0.5/min/CCU | event ingestion (mostly async via Kafka) |
| sportsbook | 4% | 0.4/min/CCU | active только если включён sportsbook |
| jackpot | 3% | 0.3/min/CCU | display refresh + contribute event |
| segmentation | 2% | 0.2/min/CCU | bonus eligibility lookup |
| store | 2% | 0.2/min/CCU | catalog browse, occasional buy |
| tournament | 2% | 0.2/min/CCU | leaderboard view, join |
| achievement | 2% | 0.2/min/CCU | progress view |
| risk-management | 2% | 0.2/min/CCU | sync risk check на deposit/withdraw |
| referral | 1% | 0.1/min/CCU | invite tracking |
| payment | 1% | 0.1/min/CCU | deposits/withdrawals — редко относительно spins |
| partner | 0.5% | 0.05/min/CCU | affiliate tracking — фоновый |
| config | 0.3% | configs cached aggressively | |
| balancer | 0.1% | event-driven | |
| notifications | 0.1% | event-driven (consumer) | |
| bi | 0% | offline reports + Kafka consumer | not in user RPS |
| back-office | 0% | admin only (~50 admins regardless of DAU) | not in user RPS |
| boilerplate | n/a | template, not deployed | — |
| Итого | ~98% | residual 2% — health checks, monitoring |
Сумма не строго 100% — это эвристика. Используй с допуском ±20%.
Формула RPS на сервис
RPS_avg(service) = DAU × CCU_ratio × actions_per_min(service) / 60
RPS_peak(service) = RPS_avg × 3.0
Где:
CCU_ratio = 0.08(8% DAU онлайн в любой момент)actions_per_min(service)— из таблицы выше
Готовые цифры RPS_peak по сервисам
| Сервис | 100 DAU | 1k DAU | 10k DAU | 100k DAU | 1M DAU |
|---|---|---|---|---|---|
| auth | 0.16 | 1.6 | 16 | 160 | 1 600 |
| core | 0.8 | 8 | 80 | 800 | 8 000 |
| game-processing | 0.64 | 6.4 | 64 | 640 | 6 400 |
| wallet | 0.48 | 4.8 | 48 | 480 | 4 800 |
| bonuses | 0.32 | 3.2 | 32 | 320 | 3 200 |
| stats | 0.16 | 1.6 | 16 | 160 | 1 600 |
| sportsbook | 0.13 | 1.3 | 13 | 130 | 1 280 |
| jackpot | 0.10 | 1.0 | 10 | 100 | 960 |
| risk-management | 0.06 | 0.6 | 6 | 64 | 640 |
| segmentation | 0.06 | 0.6 | 6 | 64 | 640 |
| store | 0.06 | 0.6 | 6 | 64 | 640 |
| tournament | 0.06 | 0.6 | 6 | 64 | 640 |
| achievement | 0.06 | 0.6 | 6 | 64 | 640 |
| referral | 0.03 | 0.3 | 3 | 32 | 320 |
| payment | 0.03 | 0.3 | 3 | 32 | 320 |
| partner | 0.02 | 0.16 | 1.6 | 16 | 160 |
| config | 0.01 | 0.1 | 1 | 9.6 | 96 |
| balancer | 0.003 | 0.03 | 0.3 | 3.2 | 32 |
| notifications | 0.003 | 0.03 | 0.3 | 3.2 | 32 |
| bi | 0 | 0 | 0 | 0 | 0 |
| back-office | 0.5 | 0.5 | 1 | 2 | 5 |
⚠️ peak coefficient 3× уже учтён.
Карта зависимостей сервисов
Получена из grep -r "SMC_*_SERVICE_URL" по всем репозиториям. Это synchronous HTTP вызовы между сервисами; асинхронные через Kafka — отдельно ниже.
Кто кого вызывает (sync HTTP)
| Сервис | Вызывает |
|---|---|
| achievement | auth, backoffice, bonus, config, game, notification, segmentation, wallet |
| auth | partner |
| back-office | config |
| balancer | backoffice |
| bi | achievement, auth, backoffice, bonus, config, partner, payments, risk-management, sportsbook, store, wallet |
| bonuses | achievement, auth, backoffice, config, game, notification, referral, segmentation, sportsbook, stats, wallet |
| core | auth, backoffice, bonus, segmentation, stats |
| game-processing | achievement, admin-auth, auth, bonus, config, core, jackpot, notification, partner, payments, segmentation, sportsbook, stats, tournament, wallet |
| jackpot | auth, game, wallet |
| partner | auth, backoffice, config, game, stats, wallet |
| payment | achievement, auth, backoffice, balancer, config, core, notification, segmentation, stats, wallet |
| referral | admin-auth, auth, config, stats, wallet |
| risk-management | auth, backoffice, bonus, config, stats, wallet |
| segmentation | auth, backoffice, stats, wallet |
| stats | achievement, auth, bonus, config, notification, wallet |
| store | bonus |
| tournament | auth, backoffice, config, game, segmentation, wallet |
| wallet | auth, backoffice, balancer, config |
| sportsbook | (no SMC_* — только Digitain webhook) |
| notifications | (нет данных — service пустой) |
| achievement | (как выше) |
Кто кого зовёт (inverted: «called by»)
| Сервис | Вызывается из |
|---|---|
| auth | ALL (universally — token validation на каждом запросе) |
| wallet | achievement, bi, bonuses, game-processing, jackpot, partner, payment, referral, risk-management, segmentation, stats, tournament |
| config | achievement, back-office, bi, bonuses, game-processing, partner, payment, referral, risk-management, stats, tournament, wallet |
| stats | bi, bonuses, core, game-processing, partner, payment, referral, risk-management, segmentation |
| back-office | achievement, balancer, bi, bonuses, core, partner, payment, risk-management, segmentation, tournament, wallet |
| bonuses | achievement, bi, core, game-processing, payment, risk-management, store, stats |
| notification | achievement, bonuses, game-processing, payment, stats |
| segmentation | achievement, bonuses, core, game-processing, payment, tournament |
| game | achievement, bonuses, jackpot, partner, payment(via core), tournament |
| achievement | bi, bonuses, game-processing, payment, stats |
| partner | auth, bi, game-processing |
| sportsbook | bi, bonuses, game-processing |
| core | game-processing, payment |
| balancer | payment, wallet |
| referral | bonuses |
| store | bi |
| jackpot | game-processing |
| tournament | game-processing |
| risk-management | bi |
Hot-path сервисы (вызываются на КАЖДОМ юзер-действии)
В порядке критичности latency:
- auth — токен валидируется на каждом запросе → агрессивный кеш (Redis + in-process) обязателен
- wallet — каждый spin = balance check + debit/credit → должен быть HA
- config — кешируется, но запрашивается чаще всех → кеш в каждом сервисе на 5+ минут
- bonuses — каждый bet проверяет wagering → кеш активных бонусов
- segmentation — bonus eligibility и AB-tests → memoize per-request
Hub сервисы (вызываются 10+ другими)
| Сервис | Зависимостей входящих | Решение для роста |
|---|---|---|
| auth | 22 | Read replicas + Redis token cache |
| wallet | 12 | Read replica для balance reads, hot-path кеш на 30s |
| config | 12 | In-process cache на сервисах + pub/sub invalidation |
| stats | 9 | Pure write — async fire-and-forget где возможно |
| back-office | 11 (но low RPS) | Read-only access от других сервисов через materialized view |
| bonuses | 8 | Кеш активных бонусов в Redis, read replica |
Критические circular зависимости
bonuses ↔ wallet: bonuses зовёт wallet (баланс), wallet зовёт bonuses (bonus balance)- Решение: сделать wallet "источник правды" по балансам, bonuses не зовёт wallet sync
core ↔ stats: core зовёт stats (chat events), stats зовёт core (?)- Проверить — в случае циркулярной зависимости вынести events в Kafka
Мёртвый код / стабы
- notifications-service — пустой (0 LoC). Если нужны notifications — реализовать отдельно
- boilerplate-service — template для новых сервисов, не разворачивается
Внешние зависимости (3rd-party)
| Сервис | 3rd-party |
|---|---|
| auth | email/SMS providers, OAuth, 2FA |
| payment | 15 PSPs (Stripe, crypto, etc.) |
| sportsbook | Digitain (webhook only) |
| balancer | Cloudflare, Namecheap, PSKZ, APISIX, PingAdmin |
| wallet | TruePlay (provably fair) |
| game-processing | game providers (likely 50+ vendors) |
| core | S3/MinIO (file uploads) |
| notifications | FCM, APNS, SendGrid (when implemented) |
Граф зависимостей (Mermaid)
Sync HTTP-зависимости (упрощённая)
Легенда
- 🟡 Hub (auth, wallet, config, stats, back-office, bonuses, notifications, segmentation) — вызываются многими; нужны read replicas / агрессивный кеш
- 🔴 Hot path (game-processing) — входная точка spin'а, fan-out на 15 сервисов
- 🟦 Critical (risk-management) — sync-блокирует payment/withdraw, latency-sensitive
- 🟢 Analytics (bi, dashed lines) — consumer-side через Kafka, sync-вызовы редкие
- ⚪ External (sportsbook=Digitain, payment=PSPs, balancer=Cloudflare) — есть 3rd-party
---
Kafka-связи (упрощённо)
Hot Path: один спин — какие сервисы трогаются?
Затраты времени по компонентам spin'а (~150ms типовой)
| Стадия | Latency P50 | P99 | Sync? |
|---|---|---|---|
| auth validate (cache hit) | 1-3ms | 10ms | sync |
| auth validate (cache miss) | 10-30ms | 100ms | sync |
| wallet debit | 15-30ms | 80ms | sync |
| bonuses check | 5-15ms | 50ms | sync |
| game provider | 50-200ms | 1000ms | sync (внешний) |
| wallet credit | 15-30ms | 80ms | sync |
| Kafka publish (≈4 events) | 1-3ms | 10ms | async |
| Sum (P50) | ~120ms | ~900ms |
При cache miss на auth + slow wallet → могут быть >500ms даже при быстром провайдере. Cache hit на auth обязателен.
Тиры архитектуры
Шкала привязки DAU к архитектурному паттерну.
| Тир | DAU max | Pattern | PG | Redis | Kafka | PgBouncer | Notes |
|---|---|---|---|---|---|---|---|
| T0 | 10 | Single VM, all-in-compose | 1 instance | 1 instance | 1 broker | no | Demo / dev |
| T1 | 1k | Single VM, separate processes | 1 primary, daily backup | 1 instance | 1 broker | optional | Small client |
| T2 | 10k | 3-5 VM, replicas | primary + replica | master + replica | 3 brokers | yes | PgBouncer mandatory >200 conns |
| T3 | 100k | K8s или 10-20 VM | primary + 2 replicas, partitioning | cluster (3+3) | 5+ brokers, partition≥32 | yes | ClickHouse for BI/stats |
| T4 | 1M | Multi-region K8s, sharding | Sharded by user_id | Multi-cluster | Dedicated analytics cluster | yes (1 per app pool) | CDN, autoscaling |
Все сервисы (22)
casino-core-service
medium Доля общего RPS: 25%
Что растёт линейно с DAU
- Chat messages — самая растущая таблица, ~3 сообщений/CCU/мин
- Story views — каждый show = upsert (с unique constraint)
- App RAM — 1-2 MB на 10 RPS
Что растёт ступенями (нелинейно)
- При 10k+ CCU — chat partitioning по datetime
- Story view upsert contention — на популярные stories спайки
Узкое место
Что сломается первым: chat_messages таблица растёт неконтролируемо
Когда: ~50,000 DAU
Как обойти: Партиционировать chat_messages по дате; old chats → cold storage; rate-limit на chat send
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 143 MB | 0.2 | 512 MB | 0.7 | 2 GB | 128 MB | 0.8 GB | 0.9 |
| 1k | 204 MB | 0.3 | 1.0 GB | 1.0 | 5 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 716 MB | 1.5 | 2.0 GB | 2.0 | 30 GB | 512 MB | 3.2 GB | 3.5 |
| 100k | 4.0 GB | 4.0 | 8.0 GB | 4.0 | 300 GB | 4096 MB | 20.0 GB | 12.0 |
| 1M | 16.0 GB | 16.0 | 32.0 GB | 16.0 | 2.9 TB | 16384 MB | 128.0 GB | 80.0 |
Запросы к БД и Redis
Профиль: 2.5 q/HTTP-request (read: 2.4, write: 0.1), Redis: 0.5 ops/req, cache hit: 80%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.1 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.8 | 0.4 | 0.1 | 0.4 | 10 |
| 1k | 8.0 | 3.8 | 0.8 | 4.0 | 10 |
| 10k | 80.0 | 38.4 | 8.0 | 40.0 | 10 |
| 100k | 800.0 | 384.0 | 80.3 | 400.0 | 10 |
| 1M | 8000.0 | 3840.0 | 803.5 | 4000.0 | 70 ⚠ PgBouncer |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- CMS + chat — открытие любой страницы. Hub для контента.
- Admin chat ban list часто опрашивается — кеш в Redis обязателен.
- Story view кафка-продьюсер: при 1M DAU peak ~2k events/sec на топик.
Связи
casino-game-processing-service
heavy Доля общего RPS: 20%
Что растёт линейно с DAU
- game_actions — 1 row/spin = 200 rows/DAU/day
- RAM app — 2-3 MB на 10 RPS (orchestrator, держит state)
- Outbound HTTP коннекты в wallet/bonuses/etc
Что растёт ступенями (нелинейно)
- Provider HTTP latency — скачок при их API throttling
- Game catalog cache invalidation — каждые 2 часа полный rebuild
- При 100k+ DAU — game_actions партиционирование по date обязательно
Узкое место
Что сломается первым: Sync HTTP вызов wallet — wallet p99 latency напрямую = spin latency
Когда: ~10,000 DAU
Как обойти: Circuit breaker на wallet calls; bulk Kafka events; партицирование game_actions; реплики app
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 102 MB | 0.2 | 262 MB | 0.5 | 1 GB | 64 MB | 0.5 GB | 0.7 |
| 100 | 184 MB | 0.3 | 512 MB | 0.7 | 3 GB | 128 MB | 0.9 GB | 1.0 |
| 1k | 256 MB | 0.5 | 1.0 GB | 1.0 | 8 GB | 256 MB | 1.5 GB | 1.5 |
| 10k | 1.0 GB | 2.0 | 4.0 GB | 4.0 | 60 GB | 1024 MB | 6.0 GB | 6.0 |
| 100k | 12.0 GB | 9.0 | 16.0 GB | 8.0 | 600 GB | 4096 MB | 32.0 GB | 18.0 |
| 1M | 96.0 GB | 36.0 | 128.0 GB | 32.0 | 5.9 TB | 16384 MB | 224.0 GB | 150.0 |
Запросы к БД и Redis
Профиль: 6.0 q/HTTP-request (read: 4.0, write: 2.0), Redis: 1.0 ops/req, cache hit: 60%, avg query latency: 15 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.1 | 0.1 | 0.1 | 0.1 | 10 |
| 100 | 0.6 | 1.0 | 1.3 | 0.6 | 10 |
| 1k | 6.4 | 10.2 | 12.8 | 6.4 | 10 |
| 10k | 64.0 | 102.4 | 128.2 | 64.0 | 10 |
| 100k | 640.0 | 1024.0 | 1281.7 | 640.0 | 52 ⚠ PgBouncer |
| 1M | 6400.0 | 10240.0 | 12817.4 | 6400.0 | 519 ⚠ PgBouncer |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Spin orchestrator — fan-out на 15 сервисов. Самый горячий путь.
- game_actions table растёт неограниченно (1 строка на spin) — нужно партиционирование @ >10k DAU.
- Sync HTTP вызов wallet — wallet p99 latency напрямую влияет на spin SLA.
- Provider callbacks (Softswiss/Slotegrator/Zenith/Hub88) — внешний latency может всплывать.
Связи
casino-wallet-service
heavy (financial-critical) Доля общего RPS: 15%
Что растёт линейно с DAU
- transactions — 400 rows/DAU/day; самая большая таблица
- DB write QPS = 3 × RPS — каждая транзакция = 3 INSERT/UPDATE
- Redis balance cache — 0.5 KB на CCU юзер, TTL 30s
Что растёт ступенями (нелинейно)
- SELECT FOR UPDATE row lock — на горячих юзерах queue растёт нелинейно
- WAL throughput — при 1k+ wQPS нужен NVMe + отдельный диск под WAL
- При 100k DAU — read replica для отчётов (выгрузки)
- При 1M DAU — шардинг по user_id (минимум 4 шарда)
Узкое место
Что сломается первым: Lock contention на balance row у активных юзеров (whale users)
Когда: ~50,000 DAU
Как обойти: Балансы в Redis с периодической сверкой; шардинг transactions по user_id; партицирование по дате; pgBouncer transaction mode
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 102 MB | 0.2 | 524 MB | 0.5 | 1 GB | 64 MB | 0.7 GB | 0.7 |
| 100 | 204 MB | 0.3 | 1.0 GB | 0.7 | 3 GB | 128 MB | 1.4 GB | 1.0 |
| 1k | 307 MB | 0.5 | 2.0 GB | 1.0 | 10 GB | 256 MB | 2.5 GB | 1.5 |
| 10k | 1.0 GB | 2.0 | 8.0 GB | 4.0 | 100 GB | 1024 MB | 10.0 GB | 6.0 |
| 100k | 12.0 GB | 9.0 | 64.0 GB | 16.0 | 1000 GB | 8192 MB | 96.0 GB | 40.0 |
| 1M | 96.0 GB | 36.0 | 256.0 GB | 64.0 | 9.8 TB | 32768 MB | 440.0 GB | 220.0 |
Запросы к БД и Redis
Профиль: 5.0 q/HTTP-request (read: 2.0, write: 3.0), Redis: 1.0 ops/req, cache hit: 70%, avg query latency: 15 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.1 | 0.0 | 10 |
| 100 | 0.5 | 0.3 | 1.4 | 0.5 | 10 |
| 1k | 4.8 | 2.9 | 14.4 | 4.8 | 10 |
| 10k | 48.0 | 28.8 | 144.1 | 48.0 | 10 |
| 100k | 480.0 | 288.0 | 1441.0 | 480.0 | 39 ⚠ PgBouncer |
| 1M | 4800.0 | 2880.0 | 14410.4 | 4800.0 | 389 ⚠ PgBouncer |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- ACID критично: SELECT FOR UPDATE на каждой транзакции.
- transactions table — самая большая таблица. Партиционирование по user_id обязательно @ >100k DAU.
- При 1M DAU — шардинг по user_id (2-4 шарда минимум).
- Read replica для отчётов back-office чтобы не блокировать primary.
- TruePlay sync HTTP — может стопорить game-action consumer; добавить timeout + DLQ.
Связи
casino-auth-service
heavy (universal hot path) Доля общего RPS: 5%
Что растёт линейно с DAU
- RAM app — растёт ~+0.5 MB на каждые 10 RPS (concurrent goroutines)
- PG sessions table — линейно по DAU (~5 KB/юзер при средней сессии)
- Redis token cache — линейно по CCU (~2 KB/юзер)
Что растёт ступенями (нелинейно)
- DB CPU — скачком при потере кеш-хита (например, 95% → 90%)
- При 100k+ DAU — нужен read replica для админских запросов
- При 1M DAU — переход sessions из PG в Redis даёт -70% DB load
Узкое место
Что сломается первым: Token validation latency — если cache miss > 5%, PG не справляется
Когда: ~30,000 DAU
Как обойти: Redis-only sessions + JWT stateless (denylist в Redis)
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 0 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 133 MB | 0.2 | 512 MB | 0.7 | 1 GB | 128 MB | 0.8 GB | 0.9 |
| 1k | 204 MB | 0.3 | 1.0 GB | 1.0 | 2 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 614 MB | 1.0 | 2.0 GB | 2.0 | 20 GB | 1024 MB | 3.6 GB | 3.0 |
| 100k | 4.0 GB | 4.0 | 8.0 GB | 4.0 | 200 GB | 4096 MB | 18.0 GB | 12.0 |
| 1M | 32.0 GB | 16.0 | 32.0 GB | 16.0 | 2.0 TB | 16384 MB | 96.0 GB | 64.0 |
Запросы к БД и Redis
Профиль: 1.5 q/HTTP-request (read: 1.5, write: 0.0), Redis: 1.0 ops/req, cache hit: 95%, avg query latency: 15 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.2 | 0.0 | 0.0 | 0.2 | 10 |
| 1k | 1.6 | 0.1 | 0.0 | 1.6 | 10 |
| 10k | 16.0 | 1.2 | 0.1 | 16.0 | 10 |
| 100k | 160.0 | 12.0 | 0.7 | 160.0 | 10 |
| 1M | 1600.0 | 120.0 | 6.9 | 1600.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Token validation на каждом запросе всех сервисов — кеш Redis ОБЯЗАТЕЛЕН.
- Сейчас sessions хранятся в Postgres — миграция в Redis снимает 70% нагрузки на DB.
- SMS/email/SumSub/Fingerprint.js — переменные затраты per-user. Бюджетировать отдельно.
- При 1M DAU рассмотреть JWT stateless с denylist в Redis вместо DB sessions.
Связи
casino-bonuses-service
heavy (every bet) Доля общего RPS: 10%
Что растёт линейно с DAU
- wagering_log — 1 row на bet (через Kafka consumer)
- user_bonuses growth = sum активных бонусов × кол-во юзеров
- Redis active_bonus cache — 1 KB/CCU
Что растёт ступенями (нелинейно)
- Скачок при крупных промо-кампаниях (free spins для всех = единоразовый INSERT batch)
- Asynq queue (5 cron) — фиксированные пики времени
- При 100k DAU — отдельный consumer для game-action.created
Узкое место
Что сломается первым: Kafka consumer lag на game-action.created — wagering progress отстаёт
Когда: ~30,000 DAU
Как обойти: Increase consumer parallelism; batch updates; кеш активных бонусов в Redis HASH; партицирование wagering_log
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 102 MB | 0.2 | 524 MB | 0.5 | 1 GB | 128 MB | 0.7 GB | 0.7 |
| 100 | 204 MB | 0.3 | 1.0 GB | 1.0 | 3 GB | 256 MB | 1.5 GB | 1.3 |
| 1k | 307 MB | 0.5 | 2.0 GB | 2.0 | 10 GB | 512 MB | 3.0 GB | 2.5 |
| 10k | 1.5 GB | 2.0 | 8.0 GB | 4.0 | 100 GB | 2048 MB | 12.0 GB | 6.0 |
| 100k | 12.0 GB | 8.0 | 32.0 GB | 8.0 | 1000 GB | 8192 MB | 52.0 GB | 24.0 |
| 1M | 64.0 GB | 32.0 | 128.0 GB | 32.0 | 9.8 TB | 32768 MB | 224.0 GB | 130.0 |
Запросы к БД и Redis
Профиль: 4.0 q/HTTP-request (read: 3.0, write: 1.0), Redis: 2.0 ops/req, cache hit: 70%, avg query latency: 15 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.1 | 10 |
| 100 | 0.3 | 0.3 | 0.3 | 0.6 | 10 |
| 1k | 3.2 | 2.9 | 3.2 | 6.4 | 10 |
| 10k | 32.0 | 28.8 | 32.3 | 64.0 | 10 |
| 100k | 320.0 | 288.0 | 323.5 | 640.0 | 14 |
| 1M | 3200.0 | 2880.0 | 3234.7 | 6400.0 | 138 ⚠ PgBouncer |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Wagering progress — каждый bet триггерит update. Самый высокий write rate из всех сервисов.
- Active bonuses cache в Redis обязателен — иначе DB не справится.
- Asynq queue (5 scheduled jobs) — отдельный worker.
- Кафка consumer game-action.created — рассмотреть batch processing для @ >100k DAU.
Связи
casino-payment-service
heavy (PSP orchestrator) Доля общего RPS: 1%
Что растёт линейно с DAU
- payment_orders — линейный, 0.2 row/DAU/day (deposits)
- PSP webhook traffic — независимый от DAU (зависит от транзакций)
Что растёт ступенями (нелинейно)
- PSP webhook bursts — могут давать пик x10 от среднего
- При смене PSP — изоляция новой интеграции
- Crypto deposits подтверждения — другой паттерн (long polling)
Узкое место
Что сломается первым: Idempotency на webhook'ах — без партиционирования payment_orders медленнее с ростом
Когда: ~100,000 DAU
Как обойти: Партицирование payment_orders по месяцу; архив PG → S3 после 1 года; rate-limit на PSP webhooks
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 0 GB | 64 MB | 0.4 GB | 0.7 |
| 100 | 133 MB | 0.2 | 512 MB | 0.7 | 2 GB | 128 MB | 0.8 GB | 1.0 |
| 1k | 204 MB | 0.3 | 1.0 GB | 1.0 | 5 GB | 256 MB | 1.5 GB | 1.5 |
| 10k | 512 MB | 0.7 | 2.0 GB | 2.0 | 50 GB | 512 MB | 3.0 GB | 2.7 |
| 100k | 4.0 GB | 3.0 | 8.0 GB | 4.0 | 500 GB | 2048 MB | 16.0 GB | 9.0 |
| 1M | 12.0 GB | 12.0 | 32.0 GB | 16.0 | 4.9 TB | 8192 MB | 80.0 GB | 45.0 |
Запросы к БД и Redis
Профиль: 4.0 q/HTTP-request (read: 2.0, write: 2.0), Redis: 0.5 ops/req, cache hit: 30%, avg query latency: 15 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.1 | 0.0 | 10 |
| 1k | 0.3 | 0.4 | 0.7 | 0.2 | 10 |
| 10k | 3.2 | 4.5 | 6.5 | 1.6 | 10 |
| 100k | 32.0 | 44.8 | 65.0 | 16.0 | 10 |
| 1M | 320.0 | 448.0 | 650.4 | 160.0 | 25 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- 15 PSP интеграций — каждая со своими webhook'ами и rate limit'ами.
- Idempotency через payment_orders — таблица не партиционирована, нужно архивировать.
- Webhook bursts от PSP могут давать пик x10 от среднего — плотный rate limit.
- in-process cache (10min TTL) — cold restart даёт спайк к зависимостям.
Связи
casino-bi-service
heavy (analytics) Доля общего RPS: 0%
Что растёт линейно с DAU
- events table растёт пропорционально всей платформы (Kafka из всех сервисов)
- PG disk — единственный сильно растущий компонент (без партицирования = катастрофа)
Что растёт ступенями (нелинейно)
- Aggregation queries — резкий скачок latency после 100M строк в events
- При >10k DAU — миграция на ClickHouse даёт сжатие 10× и скорость 100×
Узкое место
Что сломается первым: Aggregation queries блокируют write transactions
Когда: ~10,000 DAU
Как обойти: ClickHouse для events; PG только для metadata; materialized views для частых отчётов
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 102 MB | 0.1 | 1.0 GB | 1.0 | 5 GB | 64 MB | 1.2 GB | 1.2 |
| 100 | 184 MB | 0.2 | 2.0 GB | 1.5 | 15 GB | 96 MB | 2.4 GB | 1.8 |
| 1k | 256 MB | 0.3 | 4.0 GB | 2.0 | 50 GB | 128 MB | 4.5 GB | 2.5 |
| 10k | 1.0 GB | 1.0 | 16.0 GB | 4.0 | 500 GB | 256 MB | 18.0 GB | 6.0 |
| 100k | 2.0 GB | 2.0 | 64.0 GB | 16.0 | 4.9 TB | 1024 MB | 70.0 GB | 20.0 |
| 1M | 4.0 GB | 4.0 | 64.0 GB | 32.0 | 48.8 TB | 4096 MB | 120.0 GB | 40.0 |
Запросы к БД и Redis
Профиль: 0.5 q/HTTP-request (read: 0.5, write: 0.0), Redis: 0.1 ops/req, cache hit: 20%, avg query latency: 200 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1k | 0.0 | 0.0 | 0.1 | 0.0 | 10 |
| 10k | 0.0 | 0.0 | 1.0 | 0.0 | 10 |
| 100k | 0.0 | 0.0 | 10.4 | 0.0 | 10 |
| 1M | 0.0 | 0.0 | 104.2 | 0.0 | 31 ⚠ PgBouncer |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- **МИГРИРОВАТЬ НА CLICKHOUSE @ >10k DAU.** Postgres не справится с aggregations.
- Pure Kafka consumer — 46 топиков из всей платформы.
- Нет materialized views — все отчёты считают на лету.
- Disk @ 1M DAU = 50 TB / год; ClickHouse сжимает в 10x.
Связи
casino-stats-service
medium-heavy (write-heavy) Доля общего RPS: 5%
Что растёт линейно с DAU
- transactions table — 1 row на event из Kafka
- Aggregation jobs — фиксированная нагрузка независимо от DAU
Что растёт ступенями (нелинейно)
- При >100k DAU — аналогично BI, ClickHouse
- Anti-fraud turnover queries замедляются при больших суммарных таблицах
Узкое место
Что сломается первым: Aggregation на events table при write нагрузке
Когда: ~50,000 DAU
Как обойти: Партицирование events по date; read replica для aggregation; хот-кеш топ-метрик в Redis
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 133 MB | 0.2 | 512 MB | 0.7 | 3 GB | 128 MB | 0.8 GB | 0.9 |
| 1k | 204 MB | 0.3 | 2.0 GB | 1.0 | 20 GB | 256 MB | 2.5 GB | 1.5 |
| 10k | 614 MB | 1.0 | 8.0 GB | 4.0 | 200 GB | 512 MB | 9.0 GB | 5.0 |
| 100k | 4.0 GB | 4.0 | 32.0 GB | 8.0 | 2.0 TB | 2048 MB | 40.0 GB | 15.0 |
| 1M | 24.0 GB | 12.0 | 32.0 GB | 16.0 | 19.5 TB | 8192 MB | 80.0 GB | 35.0 |
Запросы к БД и Redis
Профиль: 1.2 q/HTTP-request (read: 0.0, write: 1.2), Redis: 0.0 ops/req, cache hit: 0%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.2 | 0.0 | 0.2 | 0.0 | 10 |
| 1k | 1.6 | 0.0 | 2.0 | 0.0 | 10 |
| 10k | 16.0 | 0.0 | 19.9 | 0.0 | 10 |
| 100k | 160.0 | 0.0 | 198.9 | 0.0 | 10 |
| 1M | 1600.0 | 0.0 | 1989.4 | 0.0 | 30 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- transactions table append-only без партиций — критическая проблема >100k DAU.
- Кандидат на ClickHouse @ >100k DAU.
- Aggregation jobs (NGR, GGR) — тяжёлые, на read replica если возможно.
- Anti-fraud turnover checks — sync hot path на withdrawals.
Связи
casino-achievement-service
medium-heavy (kafka fan-in) Доля общего RPS: 2%
Что растёт линейно с DAU
- user_achievements — рост ~ N achievements × N users
- Kafka throughput — 21 топика consumed
- user_points — append на каждый event
Что растёт ступенями (нелинейно)
- Leaderboards refresh — фиксированный фоновый CPU
- При >100k DAU — партицирование user_achievements обязательно
- In-process LRU dedup — НЕ shared между replicas → дубли при scale-out
Узкое место
Что сломается первым: Kafka consumer lag (game-action.created в 2 группах)
Когда: ~30,000 DAU
Как обойти: Внешний dedup через Redis SET; партицирование user_achievements; consumer parallelism +
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 133 MB | 0.2 | 512 MB | 0.7 | 3 GB | 128 MB | 0.8 GB | 0.9 |
| 1k | 204 MB | 0.3 | 1.0 GB | 1.0 | 10 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 614 MB | 1.0 | 4.0 GB | 2.0 | 100 GB | 512 MB | 5.0 GB | 3.0 |
| 100k | 4.0 GB | 3.0 | 16.0 GB | 4.0 | 1000 GB | 2048 MB | 22.0 GB | 9.0 |
| 1M | 24.0 GB | 9.0 | 64.0 GB | 16.0 | 4.9 TB | 8192 MB | 96.0 GB | 35.0 |
Запросы к БД и Redis
Профиль: 3.0 q/HTTP-request (read: 1.0, write: 2.0), Redis: 0.5 ops/req, cache hit: 40%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.1 | 0.0 | 0.1 | 0.0 | 10 |
| 1k | 0.6 | 0.4 | 1.3 | 0.3 | 10 |
| 10k | 6.4 | 3.8 | 13.3 | 3.2 | 10 |
| 100k | 64.0 | 38.4 | 133.2 | 32.0 | 10 |
| 1M | 640.0 | 384.0 | 1332.1 | 320.0 | 26 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- 21 Kafka topics consumed — самый широкий fan-in в платформе.
- user_achievements/user_points high-churn tables — партиционирование обязательно.
- In-process LRU dedup — НЕ shared между replicas, риск дублей.
- 2 consumer groups на game-action.created — мониторить лаги отдельно.
Связи
casino-back-office-service
medium (admin only) Доля общего RPS: 0% (admin RPS)
Что растёт линейно с DAU
- go_admin_logs — растёт по числу админов и активности
- Дашборды грузят данные из других сервисов
Что растёт ступенями (нелинейно)
- Большие отчёты — burst CPU (можно использовать read replica)
- Audit log retention — нужна архивация после 1 года
Узкое место
Что сломается первым: go_admin_logs растёт неограниченно
Когда: ~1,000,000 DAU
Как обойти: Архивация audit_log в S3 после 1 года; reports через read replica; sticky sessions
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 153 MB | 0.3 | 512 MB | 0.7 | 3 GB | 96 MB | 0.8 GB | 1.0 |
| 1k | 256 MB | 0.5 | 1.0 GB | 1.0 | 10 GB | 128 MB | 1.4 GB | 1.5 |
| 10k | 256 MB | 0.5 | 1.0 GB | 1.0 | 50 GB | 128 MB | 1.4 GB | 1.5 |
| 100k | 307 MB | 0.7 | 1.5 GB | 1.0 | 100 GB | 128 MB | 1.9 GB | 1.7 |
| 1M | 524 MB | 1.0 | 4.0 GB | 2.0 | 200 GB | 256 MB | 5.0 GB | 3.0 |
Запросы к БД и Redis
Профиль: 4.0 q/HTTP-request (read: 4.0, write: 0.0), Redis: 1.0 ops/req, cache hit: 90%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1k | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 10k | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100k | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1M | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- RPS зависит от количества админов (~50-200), а не от DAU юзеров.
- go_admin_logs (audit) — единственная растущая таблица. Retention 1-2 года.
- user_sessions в Redis без TTL — рестарт Redis = логаут всех админов. Использовать persistent.
Связи
casino-config-service
light (read-cached) Доля общего RPS: 0.3%
Что растёт линейно с DAU
- Почти ничего — конфиги фиксированные
- Read traffic растёт пропорционально кол-ву app-инстансов (а не DAU)
Что растёт ступенями (нелинейно)
- При >100 app-инстансов — кеш в каждом помогает
- Bulk update — N+1 запросов
Узкое место
Что сломается первым: Cache invalidation race на bulk updates
Когда: ~1,000,000 DAU
Как обойти: Локальный кеш в каждом сервисе с TTL 5 мин; pub/sub invalidation
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 51 MB | 0.05 | 262 MB | 0.5 | 0 GB | 32 MB | 0.3 GB | 0.6 |
| 100 | 81 MB | 0.07 | 262 MB | 0.5 | 0 GB | 48 MB | 0.4 GB | 0.6 |
| 1k | 102 MB | 0.1 | 262 MB | 0.5 | 0 GB | 64 MB | 0.5 GB | 0.6 |
| 10k | 204 MB | 0.2 | 524 MB | 0.5 | 1 GB | 128 MB | 0.9 GB | 0.7 |
| 100k | 409 MB | 0.5 | 1.0 GB | 1.0 | 5 GB | 256 MB | 1.7 GB | 1.5 |
| 1M | 2.0 GB | 2.0 | 2.0 GB | 1.0 | 10 GB | 1024 MB | 5.0 GB | 3.0 |
Запросы к БД и Redis
Профиль: 0.05 q/HTTP-request (read: 0.05, write: 0.0), Redis: 1.0 ops/req, cache hit: 99%, avg query latency: 5 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1k | 0.1 | 0.0 | 0.0 | 0.1 | 10 |
| 10k | 1.0 | 0.0 | 0.0 | 1.0 | 10 |
| 100k | 9.6 | 0.0 | 0.0 | 9.6 | 10 |
| 1M | 96.0 | 0.0 | 0.0 | 96.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Hit rate в Redis cache > 99% — Postgres почти простаивает.
- Кафки нет (env vars присутствуют, но не используются).
- BulkUpdate — N+1 pattern, при тысячах ключей будет медленно.
- Cache invalidation не атомарна с DB write — race в крайних случаях.
Связи
casino-jackpot-service
medium (atomic counters) Доля общего RPS: 3%
Что растёт линейно с DAU
- game_action_for_jackpots — 1 row/bet
- INCR на jackpots.current_winning_amount — горячий row
Что растёт ступенями (нелинейно)
- Win event — единоразовый burst (notification + payout)
- Cron 10-min winner selection — фиксированный пик
Узкое место
Что сломается первым: Hot row write на jackpots row под высокой bet rate
Когда: ~30,000 DAU
Как обойти: Перенести counter в Redis INCRBYFLOAT; периодически (1-min) flush в DB; партицирование game_action_for_jackpots
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 0 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 133 MB | 0.15 | 409 MB | 0.5 | 1 GB | 96 MB | 0.6 GB | 0.7 |
| 1k | 153 MB | 0.2 | 524 MB | 0.5 | 2 GB | 128 MB | 0.8 GB | 0.7 |
| 10k | 409 MB | 0.5 | 1.0 GB | 1.0 | 20 GB | 256 MB | 1.7 GB | 1.5 |
| 100k | 3.0 GB | 2.0 | 4.0 GB | 2.0 | 200 GB | 1024 MB | 8.0 GB | 4.0 |
| 1M | 12.0 GB | 8.0 | 16.0 GB | 8.0 | 2.0 TB | 4096 MB | 40.0 GB | 20.0 |
Запросы к БД и Redis
Профиль: 2.0 q/HTTP-request (read: 1.0, write: 1.0), Redis: 1.0 ops/req, cache hit: 80%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.1 | 0.0 | 0.1 | 0.1 | 10 |
| 1k | 1.0 | 0.2 | 1.0 | 1.0 | 10 |
| 10k | 9.6 | 1.9 | 9.8 | 9.6 | 10 |
| 100k | 96.0 | 19.2 | 98.1 | 96.0 | 10 |
| 1M | 960.0 | 192.0 | 980.8 | 960.0 | 18 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Hot row write на jackpots.current_winning_amount — переносить в Redis INCRBYFLOAT.
- game_action_for_jackpots — без retention, расти будет миллиардами строк.
- Cron 10-min winner selection — multi-step transaction + sync wallet payout.
- При 1M DAU переход на Redis-only counters обязателен.
Связи
casino-tournament-service
medium (leaderboards) Доля общего RPS: 2%
Что растёт линейно с DAU
- tournament_participants — растёт по числу активных турниров × DAU
- leaderboard updates — 1 ZADD на bet в активном турнире
Что растёт ступенями (нелинейно)
- End-of-tournament batch payout — фиксированный пик (sync wallet calls)
- При >10k участников — leaderboard паджинация обязательна
Узкое место
Что сломается первым: Sync wallet calls в end-of-tournament payout
Когда: ~100,000 DAU
Как обойти: Async payout через Kafka + worker; Redis ZSET для leaderboard; chunk payout (200/sec)
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 0 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 133 MB | 0.15 | 409 MB | 0.5 | 1 GB | 128 MB | 0.7 GB | 0.7 |
| 1k | 153 MB | 0.2 | 524 MB | 0.5 | 2 GB | 256 MB | 0.9 GB | 0.7 |
| 10k | 409 MB | 0.5 | 1.0 GB | 1.0 | 20 GB | 1024 MB | 2.5 GB | 1.5 |
| 100k | 3.0 GB | 2.0 | 4.0 GB | 2.0 | 200 GB | 4096 MB | 14.0 GB | 5.0 |
| 1M | 12.0 GB | 8.0 | 16.0 GB | 8.0 | 2.0 TB | 16384 MB | 64.0 GB | 24.0 |
Запросы к БД и Redis
Профиль: 2.5 q/HTTP-request (read: 1.5, write: 1.0), Redis: 2.0 ops/req, cache hit: 90%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.1 | 0.0 | 0.1 | 0.1 | 10 |
| 1k | 0.6 | 0.1 | 0.7 | 1.3 | 10 |
| 10k | 6.4 | 1.0 | 6.5 | 12.8 | 10 |
| 100k | 64.0 | 9.6 | 65.4 | 128.0 | 10 |
| 1M | 640.0 | 96.0 | 653.9 | 1280.0 | 11 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Redis sorted sets (ZSET) — обязательно для leaderboards.
- End-of-tournament batch payout (sync wallet calls) — фиксированный пик.
- Tie-break logic — внимательно с consistency между Redis cache и DB.
Связи
casino-segmentation-service
medium (recalc loop) Доля общего RPS: 2%
Что растёт линейно с DAU
- segmentation_users — линейно по числу сегментов × юзеров
- 5-секундный recalc loop — фоновый CPU постоянный
Что растёт ступенями (нелинейно)
- Большие сегменты с правилами на stats — медленная переоценка
- Каждый новый сегмент = +5%-10% постоянной нагрузки
Узкое место
Что сломается первым: 5-сек recalc loop под большим количеством сегментов
Когда: ~50,000 DAU
Как обойти: Дельта-recalc вместо full; кеш сегментов в Redis 30 sec; разделить cron heavy/light сегментов
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 0 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 133 MB | 0.15 | 409 MB | 0.5 | 0 GB | 96 MB | 0.6 GB | 0.7 |
| 1k | 153 MB | 0.2 | 524 MB | 0.5 | 1 GB | 128 MB | 0.8 GB | 0.7 |
| 10k | 409 MB | 0.7 | 2.0 GB | 2.0 | 10 GB | 256 MB | 2.7 GB | 2.7 |
| 100k | 1.5 GB | 2.0 | 8.0 GB | 4.0 | 100 GB | 1024 MB | 11.0 GB | 6.0 |
| 1M | 8.0 GB | 8.0 | 32.0 GB | 16.0 | 1000 GB | 4096 MB | 44.0 GB | 24.0 |
Запросы к БД и Redis
Профиль: 3.0 q/HTTP-request (read: 2.0, write: 1.0), Redis: 0.5 ops/req, cache hit: 70%, avg query latency: 5 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.1 | 0.0 | 0.1 | 0.0 | 10 |
| 1k | 0.6 | 0.4 | 0.7 | 0.3 | 10 |
| 10k | 6.4 | 3.8 | 6.9 | 3.2 | 10 |
| 100k | 64.0 | 38.4 | 69.2 | 32.0 | 10 |
| 1M | 640.0 | 384.0 | 692.1 | 320.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- 5-секундный recalc loop — при больших сегментах фоновый CPU будет постоянно высоким.
- Asynq concurrency 30 — настраивай отдельно от HTTP концурентности.
- Membership чтения — без Redis cache, при росте DAU добавить кеш на 30-60 сек.
- WebSocket индирект через notification-service.
Связи
casino-risk-management-service
medium (sync withdraw path) Доля общего RPS: 2%
Что растёт линейно с DAU
- risk_events — 1 row на каждое значимое событие (deposit, withdraw)
- alerts — линейно от триггеров правил
- PEP cache в Redis — 24h TTL
Что растёт ступенями (нелинейно)
- Регуляторное хранение 5-7 лет = unbounded growth без партицирования
- Sync withdraw path — latency-critical
- PEP/AML провайдер (Dilisense) rate limit — спайки на регистрациях
Узкое место
Что сломается первым: risk_events table grows; sync /scoring-system latency блокирует withdrawals
Когда: ~50,000 DAU
Как обойти: Партицирование events по месяцу + холодное в S3; bloom filter для blacklist; circuit breaker на PEP
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 0 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 133 MB | 0.2 | 512 MB | 0.7 | 2 GB | 128 MB | 0.8 GB | 0.9 |
| 1k | 204 MB | 0.3 | 1.0 GB | 1.0 | 5 GB | 256 MB | 1.5 GB | 1.3 |
| 10k | 614 MB | 1.0 | 4.0 GB | 2.0 | 50 GB | 512 MB | 5.0 GB | 3.0 |
| 100k | 4.0 GB | 3.0 | 16.0 GB | 4.0 | 500 GB | 2048 MB | 22.0 GB | 9.0 |
| 1M | 24.0 GB | 9.0 | 64.0 GB | 16.0 | 4.9 TB | 8192 MB | 96.0 GB | 35.0 |
Запросы к БД и Redis
Профиль: 3.0 q/HTTP-request (read: 2.0, write: 1.0), Redis: 1.0 ops/req, cache hit: 80%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.1 | 0.0 | 0.1 | 0.1 | 10 |
| 1k | 0.6 | 0.3 | 0.7 | 0.6 | 10 |
| 10k | 6.4 | 2.6 | 6.7 | 6.4 | 10 |
| 100k | 64.0 | 25.6 | 67.5 | 64.0 | 10 |
| 1M | 640.0 | 256.0 | 674.7 | 640.0 | 14 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- **Регуляторное хранение 5-7 лет** — партиционирование событий + холодное хранилище.
- Sync hot path на /scoring-system + /risk-summary в payment withdraw flow — latency-critical.
- PEP/AML провайдер (Dilisense) — sync HTTP, добавить circuit breaker.
- Blacklist должен быть в Redis (или bloom filter) для быстрых lookup.
Связи
casino-sportsbook-service
medium (Digitain webhook) Доля общего RPS: 4%
Что растёт линейно с DAU
- bet_operations — 1 row/bet через Digitain webhook
- Sessions — 1 row на старт/конец сессии
Что растёт ступенями (нелинейно)
- Burst при старте популярных матчей (live betting)
- Settlement runs пакетные — стабильный пик
- При 10k+ — нужен Redis для auth token cache (сейчас sync HTTP к auth)
Узкое место
Что сломается первым: Auth-сервис latency на каждом webhook — нет локального кеша
Когда: ~10,000 DAU
Как обойти: Добавить Redis для auth token cache; шардинг сессий; rate-limit на DebitByBatch
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.5 | 0 GB | — | 0.3 GB | 0.6 |
| 100 | 133 MB | 0.2 | 512 MB | 0.7 | 2 GB | — | 0.6 GB | 0.9 |
| 1k | 204 MB | 0.3 | 1.0 GB | 1.0 | 5 GB | — | 1.2 GB | 1.3 |
| 10k | 614 MB | 1.0 | 4.0 GB | 2.0 | 50 GB | 256 MB | 5.0 GB | 3.0 |
| 100k | 4.0 GB | 3.0 | 16.0 GB | 4.0 | 500 GB | 1024 MB | 20.0 GB | 9.0 |
| 1M | 24.0 GB | 12.0 | 64.0 GB | 16.0 | 4.9 TB | 4096 MB | 88.0 GB | 45.0 |
Запросы к БД и Redis
Профиль: 5.0 q/HTTP-request (read: 3.0, write: 2.0), Redis: 0.2 ops/req, cache hit: 30%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.1 | 0.3 | 0.3 | 0.0 | 10 |
| 1k | 1.3 | 2.7 | 2.6 | 0.3 | 10 |
| 10k | 12.8 | 26.9 | 25.7 | 2.6 | 10 |
| 100k | 128.0 | 268.8 | 257.4 | 25.6 | 10 |
| 1M | 1280.0 | 2688.0 | 2573.9 | 256.0 | 79 ⚠ PgBouncer |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Redis сейчас 0 — нужно добавить хотя бы для auth token cache (DOS защита).
- Digitain webhook DebitByBatch/RollBackByBatch — внутри multi-step DB transaction + Kafka.
- Burst при старте популярных матчей — горизонтальное масштабирование подов.
- Settlement runs пакетные — мониторить хвост хвоста.
Связи
casino-balancer
light (geo-redirect) Доля общего RPS: 0.1%
Что растёт линейно с DAU
- Memory — почти не растёт (GeoIP2 фиксированный, ~100 MB)
- DB — domain registry, фиксированный размер
Что растёт ступенями (нелинейно)
- Provisioning workflows — внешние API rate limits (Cloudflare/Namecheap)
- Domain мониторинг — фиксированный фоновый трафик
Узкое место
Что сломается первым: Внешние API провайдеров (Cloudflare/Namecheap rate limits)
Когда: ~1,000,000 DAU
Как обойти: Горизонтальное масштабирование (stateless); кеш GeoIP lookup в Redis; queue провижионинга
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 81 MB | 0.1 | 262 MB | 0.3 | 0 GB | — | 0.3 GB | 0.4 |
| 100 | 122 MB | 0.15 | 262 MB | 0.3 | 0 GB | — | 0.4 GB | 0.5 |
| 1k | 153 MB | 0.2 | 262 MB | 0.3 | 0 GB | — | 0.4 GB | 0.5 |
| 10k | 307 MB | 0.5 | 524 MB | 0.5 | 2 GB | — | 0.8 GB | 1.0 |
| 100k | 1.0 GB | 2.0 | 1.0 GB | 1.0 | 20 GB | — | 2.0 GB | 3.0 |
| 1M | 8.0 GB | 8.0 | 4.0 GB | 2.0 | 200 GB | — | 12.0 GB | 10.0 |
Запросы к БД и Redis
Профиль: 1.0 q/HTTP-request (read: 1.0, write: 0.0), Redis: 0.0 ops/req, cache hit: 0%, avg query latency: 5 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1k | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 10k | 0.3 | 0.3 | 0.1 | 0.0 | 10 |
| 100k | 3.2 | 3.2 | 0.7 | 0.0 | 10 |
| 1M | 32.0 | 32.0 | 6.9 | 0.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Это NOT load balancer — это geo-routing service (mirror domains).
- GeoIP2 in-memory — 100 MB на инстанс, легко горизонтально масштабируется.
- Domain provisioning через Cloudflare/Namecheap/PSKZ — внешние API rate limits.
- Не на критическом пути — failover на DNS-уровне.
Связи
casino-store-service
light Доля общего RPS: 2%
Что растёт линейно с DAU
- user_products — 1 row на покупку
- purchase logs — append-only
Что растёт ступенями (нелинейно)
- При больших промо — burst закупок
- Inventory consistency — race conditions в multi-service flow
Узкое место
Что сломается первым: Sync wallet/bonus/achievement calls на каждую покупку
Когда: ~100,000 DAU
Как обойти: Inventory hold + async fulfillment; Saga pattern для distributed transaction
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 61 MB | 0.05 | 262 MB | 0.3 | 0 GB | 32 MB | 0.3 GB | 0.4 |
| 100 | 81 MB | 0.08 | 409 MB | 0.5 | 1 GB | 48 MB | 0.5 GB | 0.6 |
| 1k | 102 MB | 0.1 | 524 MB | 0.5 | 2 GB | 64 MB | 0.7 GB | 0.6 |
| 10k | 256 MB | 0.3 | 1.0 GB | 1.0 | 10 GB | 128 MB | 1.4 GB | 1.3 |
| 100k | 1.0 GB | 1.0 | 4.0 GB | 2.0 | 100 GB | 512 MB | 6.0 GB | 3.0 |
| 1M | 8.0 GB | 6.0 | 16.0 GB | 4.0 | 1000 GB | 2048 MB | 26.0 GB | 10.0 |
Запросы к БД и Redis
Профиль: 4.0 q/HTTP-request (read: 2.0, write: 2.0), Redis: 0.5 ops/req, cache hit: 60%, avg query latency: 5 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.1 | 0.1 | 0.1 | 0.0 | 10 |
| 1k | 0.6 | 0.5 | 1.3 | 0.3 | 10 |
| 10k | 6.4 | 5.1 | 12.9 | 3.2 | 10 |
| 100k | 64.0 | 51.2 | 128.7 | 32.0 | 10 |
| 1M | 640.0 | 512.0 | 1286.9 | 320.0 | 13 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Каждая покупка делает 3-4 sync вызова (wallet, bonus, achievement, auth) — нет distributed transaction.
- Inventory consistency: race условия между local insert и remote wallet charge.
- Use goose migrations (другой инструмент чем у большинства).
Связи
casino-partner-service
light (polling) Доля общего RPS: 0.5%
Что растёт линейно с DAU
- affilka_users — линейно по новым регистрациям
- manual_user_activity — растёт по кол-ву событий
- Hourly sync — фиксированный пик в начале часа
Что растёт ступенями (нелинейно)
- 5 cron jobs synci с Affilka/Alanbase — burst в :00
- Disabled Kafka consumers — реал-тайм недоступен (polling lag до 1ч)
Узкое место
Что сломается первым: manual_user_activity рост unbounded; hourly burst к Affilka API
Когда: ~100,000 DAU
Как обойти: Партицирование activity по месяцу; включить Kafka consumers; staggered cron windows
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 61 MB | 0.05 | 262 MB | 0.3 | 0 GB | 32 MB | 0.3 GB | 0.4 |
| 100 | 81 MB | 0.07 | 409 MB | 0.5 | 2 GB | 48 MB | 0.5 GB | 0.6 |
| 1k | 102 MB | 0.1 | 524 MB | 0.5 | 5 GB | 64 MB | 0.6 GB | 0.6 |
| 10k | 256 MB | 0.3 | 1.0 GB | 1.0 | 50 GB | 128 MB | 1.3 GB | 1.3 |
| 100k | 1.0 GB | 1.0 | 4.0 GB | 2.0 | 500 GB | 512 MB | 5.0 GB | 3.0 |
| 1M | 4.0 GB | 4.0 | 16.0 GB | 8.0 | 4.9 TB | 2048 MB | 24.0 GB | 12.0 |
Запросы к БД и Redis
Профиль: 2.0 q/HTTP-request (read: 1.5, write: 0.5), Redis: 0.2 ops/req, cache hit: 50%, avg query latency: 5 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1k | 0.2 | 0.1 | 0.1 | 0.0 | 10 |
| 10k | 1.6 | 1.2 | 0.9 | 0.3 | 10 |
| 100k | 16.0 | 12.0 | 8.7 | 3.2 | 10 |
| 1M | 160.0 | 120.0 | 86.9 | 32.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Affilka/Alanbase синки — 5 hourly cron jobs. Spike нагрузки в начале каждого часа.
- Disabled Kafka consumers (4 шт) — реал-тайм атрибуция отключена → polling lag до 1 часа.
- manual_user_activity и affilka_users без партиционирования — рост неограничен.
Связи
casino-referral-service
light Доля общего RPS: 1%
Что растёт линейно с DAU
- referrals — 1 row на новую регистрацию через линк
- Closure table до глубины 5 — линейно от регистраций
Что растёт ступенями (нелинейно)
- Monthly commission run (28-31 число, 23:59 UTC) — большой single-pass через всю closure table
- Concurrency 16 sync calls к stats может перегружать stats-сервис
Узкое место
Что сломается первым: Monthly commission run scaling — sync calls к stats не справляются при росте дерева
Когда: ~100,000 DAU
Как обойти: Bulk batch к stats; ограничить concurrency 8; разбить на chunks по 10k участников
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 61 MB | 0.05 | 262 MB | 0.3 | 0 GB | — | 0.3 GB | 0.4 |
| 100 | 81 MB | 0.07 | 262 MB | 0.3 | 0 GB | — | 0.4 GB | 0.4 |
| 1k | 102 MB | 0.1 | 262 MB | 0.3 | 0 GB | — | 0.4 GB | 0.4 |
| 10k | 204 MB | 0.2 | 524 MB | 0.5 | 5 GB | — | 0.7 GB | 0.7 |
| 100k | 819 MB | 1.0 | 2.0 GB | 1.0 | 50 GB | — | 3.0 GB | 2.0 |
| 1M | 3.0 GB | 4.0 | 8.0 GB | 2.0 | 500 GB | — | 11.0 GB | 6.0 |
Запросы к БД и Redis
Профиль: 2.0 q/HTTP-request (read: 1.5, write: 0.5), Redis: 0.0 ops/req, cache hit: 0%, avg query latency: 5 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1k | 0.3 | 0.5 | 0.2 | 0.0 | 10 |
| 10k | 3.2 | 4.8 | 1.6 | 0.0 | 10 |
| 100k | 32.0 | 48.0 | 16.3 | 0.0 | 10 |
| 1M | 320.0 | 480.0 | 163.5 | 0.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- **Monthly commission run** (23:59 UTC, дни 28-31) — отдельный пик от steady-state.
- Closure table до глубины 5 — pagination обязателен на больших деревьях.
- Concurrency 16 sync calls к stats — может перегружать stats-service.
- Postgres 9 таблиц без TTL/partitioning.
Связи
casino-notifications-service
medium (multi-channel fan-out) Доля общего RPS: 0.1%
Что растёт линейно с DAU
- notifications_log — линейно по событиям
- Provider API calls (FCM/Email/SMS) — линейно
Что растёт ступенями (нелинейно)
- Marketing campaigns — burst x10-100 за минуты
- Provider rate limits (SMS 100/sec, FCM 600k/min)
Узкое место
Что сломается первым: Fan-out amplification: 1 событие → O(users × channels) вызовов
Когда: ~50,000 DAU
Как обойти: Batch sending через Kafka producer; rate-limit per provider; в priority queue по типу
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 102 MB | 0.1 | 262 MB | 0.5 | 1 GB | 64 MB | 0.4 GB | 0.6 |
| 100 | 153 MB | 0.2 | 409 MB | 0.5 | 3 GB | 96 MB | 0.6 GB | 0.7 |
| 1k | 204 MB | 0.3 | 524 MB | 0.5 | 10 GB | 128 MB | 0.8 GB | 0.8 |
| 10k | 614 MB | 1.0 | 1.0 GB | 1.0 | 100 GB | 256 MB | 1.9 GB | 2.0 |
| 100k | 4.0 GB | 3.0 | 4.0 GB | 2.0 | 1000 GB | 1024 MB | 9.0 GB | 5.0 |
| 1M | 24.0 GB | 12.0 | 16.0 GB | 4.0 | 9.8 TB | 4096 MB | 44.0 GB | 16.0 |
Запросы к БД и Redis
Профиль: 2.0 q/HTTP-request (read: 1.0, write: 1.0), Redis: 1.0 ops/req, cache hit: 70%, avg query latency: 10 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|---|---|---|---|---|
| 10 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 100 | 0.0 | 0.0 | 0.0 | 0.0 | 10 |
| 1k | 0.0 | 0.0 | 0.1 | 0.0 | 10 |
| 10k | 0.3 | 0.1 | 0.7 | 0.3 | 10 |
| 100k | 3.2 | 1.0 | 6.7 | 3.2 | 10 |
| 1M | 32.0 | 9.6 | 66.7 | 32.0 | 10 |
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- **Не stub — 26k LoC**, 4 Kafka consumer groups, 6 каналов (bell/popup/email/SMS/Viber/Telegram/WhatsApp).
- Fan-out amplification: O(users × channels) sync вызовов на 1 inbound message.
- Provider rate limits: SMS — 100/sec, FCM — 600k/min — учитывать.
- Затраты SMS/email scale linearly с DAU.
Связи
casino-boilerplate-service
n/a (template, не деплоится) Доля общего RPS: —
Что растёт линейно с DAU
- Не применимо — это шаблон, не деплоится
Что растёт ступенями (нелинейно)
Узкое место
Что сломается первым: —
Когда: ~0 DAU
Как обойти: При создании реального сервиса — заполнить эту секцию
Минимальные ресурсы по DAU
Включает app + Postgres + Redis (single instance, +30% headroom). Для HA умножай app ×2-4, DB ×2.
| DAU | App RAM | App CPU | DB RAM | DB CPU | DB Disk/yr | Redis | Total RAM | Total CPU |
|---|---|---|---|---|---|---|---|---|
| 10 | 51 MB | 0.05 | — | — | — | — | 0.05 GB | 0.05 |
| 100 | 51 MB | 0.05 | — | — | — | — | 0.05 GB | 0.05 |
| 1k | 51 MB | 0.05 | — | — | — | — | 0.05 GB | 0.05 |
| 10k | 51 MB | 0.05 | — | — | — | — | 0.05 GB | 0.05 |
| 100k | 51 MB | 0.05 | — | — | — | — | 0.05 GB | 0.05 |
| 1M | 51 MB | 0.05 | — | — | — | — | 0.05 GB | 0.05 |
Запросы к БД и Redis
Профиль: 0.0 q/HTTP-request (read: 0.0, write: 0.0), Redis: 0.0 ops/req, cache hit: 0%, avg query latency: 5 ms
| DAU | RPS peak | DB read QPS | DB write QPS | Redis QPS | Connection pool |
|---|
Pool sizing: MAX(10, ceil((rd_QPS + wr_QPS) × avg_query_ms / 1000 × 1.5))
Особенности и риски
- Это шаблон для новых сервисов. Не сайзится и не деплоится.
- При создании нового сервиса — клонируется и переименовывается.