Три варианта: стоимость, восстановление и сохранность
Один сервер — исходная конфигурация для проверки продукта; его способность выдержать нагрузку ещё нужно измерить. Варианты различаются резервированием, сроком восстановления и риском потери данных. Требование сохранности заказов и оплат остаётся обязательным, а не согласием на потери в дешёвой схеме.
| Вариант | Серверов | Для чего | Потеря при аварии | Простой при аварии | Цена |
|---|---|---|---|---|---|
| 1 · Прототип | 2; внешний backup отдельно | Проверка продукта и демо; приёмка сохранности обязательна | ненулевая; цель архива WAL до 1 минуты требует проверки | цель 2–4 часа | база сравнения 1× |
| 2 · Умеренная | 4 prod + 2 staging; облачные сервисы отдельно | Коммерческий запуск после приёмки рисков | последние записи возможны; сверка не восстанавливает содержание заказа | цель до 30 минут | оценка ≈ 3× |
| 3 · Энтерпрайз | 7 prod + 3–4 staging; облачные сервисы отдельно | Работа по договору с проверенным SLA | цель RPO=0 при покрываемом отказе узла/зоны | возможен перерыв на переключение БД | оценка ≈ 7–8× |
Варианты описывают этапы резервирования модульного монолита. Переход требует проверить общие файлы, фоновые задачи, подключение к БД и переключение. Исходный анализ предлагал старт со второго варианта; текущий выбор для проверки продукта — MTN по базовой схеме. Это не отменяет приёмку требования сохранности данных.
Состав по вариантам (прод + staging)
| Узел | 1 · Прототип | 2 · Умеренная | 3 · Энтерпрайз |
|---|---|---|---|
| L7-балансировщик | — (nginx на сервере) | 1 управляемый | 1 управляемый, 3 зоны |
| Серверы приложения | 1 × 4 vCPU / 16 ГБ / 200 ГБ SSD (вместе с БД) | 1 × 4 vCPU / 16 ГБ / 50 ГБ SSD | 2 × 4 vCPU / 16 ГБ / 50 ГБ SSD, разные зоны |
| PostgreSQL | на том же сервере | управляемый, 2 хоста × 4 vCPU / 16 ГБ / 200 ГБ SSD | управляемый, 3 хоста (3 зоны) × 4 vCPU / 16 ГБ / 200 ГБ SSD |
| Мониторинг и бэкапы (ops) | внешний сервис доступности | 1 × 2 vCPU / 8 ГБ / 100 ГБ | 1 × 2 vCPU / 8 ГБ / 200 ГБ |
| Bastion | — | — | 1 × 2 vCPU / 2 ГБ / 20 ГБ |
| NAT-шлюз со статическим IP | — (свой IP сервера) | 1 | 1 |
| Объектное хранилище (S3) | бэкапы во втором регионе | фото + бэкапы во втором регионе | фото + бэкапы во втором регионе + логи |
| Staging | 1 × 2 vCPU / 8 ГБ / 80 ГБ | 1 VM + БД на 1 хосте | 1–2 VM + БД на 2 хостах |
Общие требования для всех вариантов
- Регион — Африка; все копии данных (БД, реплики, бэкапы, фото, логи) — в Африке.
- Диски — SSD; для БД ≥ 3 000 IOPS (вариант 1) и ≥ 6 000 IOPS, ≥ 200 МБ/с (варианты 2–3).
- Исходящий доступ к Paystack, провайдеру карт и AirLabs; входящие вебхуки Paystack по HTTPS.
- S3-совместимое объектное хранилище с версионированием и запретом удаления (Object Lock).
- ОС Ubuntu 24.04 LTS; прод не делит серверы и БД с другими проектами.
Расчёт нагрузки
Для расчётного сценария принимаем ≈ 160 одновременных поездок. Загрузка 80% по часам сама по себе не определяет пик. Синтетический демо-месяц дал ориентир 3,7 заказа на машину в сутки при 66% загрузки; пересчёт до ≈ 4,5 при 80% и ≈ 900 заказов в сутки — предположение модели. Пиковый час ≈ 100 заказов (среднее × 2,5) нужно подтвердить профилем пилота и испытанием.
| Источник | Частота исходной модели; сверить с ревизией | Расчётные RPS |
|---|---|---|
| Телеметрия водителей, 200 онлайн | пакет 5–15 с в движении, 60 с на стоянке | 20 |
| Опросы приложения водителя | геозона 3 с, чат 5 с, список чатов 15 с | 120 |
| Клиенты, ≈ 80 с открытым приложением | заказ 5 с, позиция 10 с, трек 10 с, чат 5 с | 55 |
| Пульс WebSocket | 25 с, ≈ 320 соединений | 13 |
| Операторы, партнёры, заказы, цены | по событиям | 20 |
| Итого | ≈ 230–250 |
Плановая модель: ≈ 70 записей и ≈ 800 простых чтений БД в секунду, WAL ≈ 0,5 МБ/с. Цель нагрузочного испытания с запасом ×3: 750 RPS, 1 000 WebSocket, 2 400 чтений/с. Способность 4 vCPU выдержать этот профиль и предел масштабирования по числу машин ещё не измерены.
Один заказ на бэкенде
Исходная оценка базовой поездки: около 10 событий, 50–70 строк доставки уведомлений, 4–6 переводов в учёте (≈ 20 строк), ≈ 60 HTTP-запросов. Продления, сообщения, координаты, повторы и сбои добавляют операции; подписка и чаевые имеют отдельные циклы. Эти числа не заменяют трассировку текущей ревизии и замер нагрузки.
Доработки кода, обязательные для всех вариантов
- Исключить телеметрию из журнала заказа — иначе ≈ 1,4 млн неудаляемых строк в сутки (≈ 250 ГБ в год).
- Хранение уведомлений 30 дней и потолок повторов — сейчас
notify.*растёт бесконечно. - Пул соединений к БД 25–30 вместо 10.
- Свой OSRM и платный провайдер тайлов: в проде нет маршрутизации, а публичные тайлы OSM запрещены правилами.
- Проверить на принимаемой ревизии защиту повторов создания заказа и платежей. Она уже реализована локально; настоящий Paystack sandbox ещё не подтверждён.
Что добавляется для вариантов 2 и 3 — в их вкладках.
Прототип: всё на одном сервере
Исходная схема для проверки продукта: приложение, база и маршруты на одной VM, копии — вне неё. Цель восстановления — 2–4 часа; объём возможной потери зависит от реально доставленных копий WAL и проверяется учениями. Сверка Paystack помогает найти внешнюю оплату, но не восстанавливает содержание потерянного заказа. Пока приёмка не пройдена, схема не подтверждает выполнение требования нулевой потери заказов и оплат.
| Сервер | Количество | Назначение |
|---|---|---|
| Основной сервер | 1 | приложения для клиентов, водителей, парков и партнёров, база данных, маршруты |
| Тестовый сервер | 1 | проверка новой версии перед выпуском |
| Хранилище бэкапов | 1 | копии базы во втором регионе, удалить их нельзя |
| Мониторинг доступности | сервис | сообщение в Telegram, если сайт перестал отвечать |
Подходит: пилот с одним-двумя парками, первые недели. Не подходит: договоры с отелями и агентствами с гарантиями доступности.
Схема
flowchart LR
U([Клиенты, водители, парки]) -->|HTTPS, WebSocket| P
PS([Paystack]) -->|вебхуки| P
subgraph R1[Регион 1, Африка]
P[prod-1
nginx · parkmanager
PostgreSQL · OSRM]
S[staging-1
тестовая копия]
end
subgraph R2[Регион 2, Африка]
B[(S3: WAL каждые 60 с
ночной бэкап · Object Lock)]
end
P -->|архив WAL, бэкап| B
M([Внешний мониторинг]) -.->|/healthz раз в минуту| P
Спецификация
| Узел | vCPU | RAM | Диск | Сеть | Где |
|---|---|---|---|---|---|
| prod-1 | 4, 100% | 16 ГБ | 200 ГБ SSD, ≥ 3 000 IOPS (локальный NVMe или сетевой SSD) | 1 Гбит/с, публичный IP, порты 80/443 и 22 только с офисного IP | регион 1 |
| staging-1 | 2 | 8 ГБ | 80 ГБ SSD | публичный IP, 80/443 | регион 1 |
| S3-бакет бэкапов | ≈ 100 ГБ; версионирование, Object Lock 14 дней, шифрование | — | регион 2 | ||
Что нужно от площадки
- VM с гарантированными ядрами (не burstable) и SSD с заявленными IOPS.
- Ежедневные снапшоты диска prod-1 (если доступны), хранение 7 дней.
- S3-совместимое хранилище во втором регионе или ДЦ в Африке.
- Исходящий доступ к Paystack, AirLabs, провайдеру карт; входящий HTTPS для вебхуков Paystack.
- Ubuntu 24.04 LTS; DNS-записи для поддоменов
order. driver. fleet. partner. admin. auth.
Минимально допустимо держать staging на prod-1 — отдельной БД и отдельным сервисом с лимитами памяти, процессора и диска. Без лимитов тест может положить прод: так уже было на текущем сервере.
Что проверить по нагрузке
≈ 250 RPS — расчётный профиль, не измеренная загрузка CPU. План распределения 16 ГБ: shared_buffers 4 ГБ, OSRM 4–6 ГБ, приложение ≈ 1 ГБ, остаток — кэш ОС. Реальный размер карты Нигерии, рабочий набор БД и запас памяти нужно измерить. Оценка диска: ≈ 65 ГБ данных к концу года плюс WAL, индексы и запас ×2; её проверяют по скорости роста данных.
Цели и механизмы приёмки
| Цель / требование | Механизм |
|---|---|
| RPO ≤ 1 мин | archive_mode=on, archive_timeout=60, wal-g/pgBackRest непрерывно пишут WAL в S3 второго региона |
| Сохранность коммита на диске | fsync=on, full_page_writes=on, synchronous_commit=on — не трогать |
| Бэкап не удалить по ошибке или при взломе | Object Lock 14 дней; ключи записи без права удаления |
| Восстановление работает | раз в месяц — восстановление на staging-1 по чек-листу: число заказов, сумма проводок, последние платежи |
Ручные процедуры
| Ситуация | Действие | Время |
|---|---|---|
| Сервер или диск погиб | новая VM из образа → base backup + WAL → DNS | 2–4 ч |
| Потеряна последняя минута | по выписке Paystack за интервал найти оплаты без зачисления, зачислить по reference (операция идемпотентна) | 30 мин |
| Ежедневно | отчёт: оплаты pending > 1 ч, заказы застрявшие в статусе, сверка бухгалтерии | 15 мин |
| Обновление ОС | ночное окно | простой 5–10 мин |
Алерты
Сервер недоступен · диск > 75% · не прошёл архив WAL или ночной бэкап. В Telegram.
Настройки
nginx: Upgrade/Connection для WebSocket, proxy_read_timeout 120s, тело до 10 МБ. Пул приложения 25–30. Обязательные доработки кода — во вкладке «Сравнение», блок 3.
Умеренная надёжность: реплика базы и ручной разбор платежей
База размещается на двух серверах в разных зонах с переключением при отказе. Асинхронная репликация допускает потерю последних записей; такая схема не выполняет безусловное требование нулевой потери заказов. Приложение остаётся одним узлом. Срок восстановления и частота ручного разбора платежей подтверждаются испытаниями и эксплуатацией, а не этой оценкой.
| Сервер | Количество | Назначение |
|---|---|---|
| Балансировщик | 1 | вход для всех пользователей, защищённое соединение; позволяет заменить сервер без смены адресов |
| Сервер приложения | 1 | приложения для клиентов, водителей, парков и партнёров, маршруты |
| База данных | 2 | заказы и деньги; второй сервер — горячая копия в другой зоне |
| Сервер эксплуатации | 1 | мониторинг, оповещения, ночные бэкапы, сверка денег |
| Хранилище | 2 | фото водителей и машин; бэкапы во втором регионе |
| Тестовый стенд | 2 | сервер и база для проверки новой версии |
Подходит: коммерческий запуск и первые месяцы роста.
Схема
flowchart TB
U([Пользователи и вебхуки Paystack]) -->|HTTPS · WebSocket| LB[L7-балансировщик · managed · TLS]
LB --> APP
subgraph ZA[Зона A · регион 1]
APP[app-1
parkmanager · OSRM]
PG1[(PostgreSQL мастер)]
end
subgraph ZB[Зона B · регион 1]
PG2[(PostgreSQL реплика)]
OPS[ops-1 · мониторинг · бэкапы · сверки]
end
APP --> PG1
PG1 ==>|репликация · автопереключение| PG2
APP --> MEDIA[(S3: фото)]
APP --> NAT[NAT-шлюз · статический IP]
NAT --> EXT([Paystack · карты · AirLabs])
OPS --> BK[(Регион 2 · S3 бэкапы · Object Lock)]
Спецификация
| Узел | Кол-во | vCPU | RAM | Диск | Сеть / размещение |
|---|---|---|---|---|---|
| L7-балансировщик | 1 | managed; ≥ 1 000 RPS, ≥ 2 000 WebSocket, idle timeout ≥ 120 с | публичный IP, TLS-сертификаты с автопродлением | ||
| app-1 | 1 | 4, 100% | 16 ГБ | 50 ГБ SSD, ≥ 2 000 IOPS | зона A, только приватный IP |
| PostgreSQL (managed) | 2 | 4 | 16 ГБ | 200 ГБ SSD, ≥ 6 000 IOPS, ≥ 200 МБ/с | зоны A и B; автопереключение; PITR 14 дней |
| ops-1 | 1 | 2 | 4–8 ГБ | 100 ГБ SSD | зона B, приватный IP |
| NAT-шлюз | 1 | managed | статический публичный IP | ||
S3 pm-prod-media | 1 | ≈ 150 ГБ/год, версионирование | регион 1 | ||
S3 pm-prod-backup | 1 | Object Lock 35 дней, хранение 60 дней | регион 2 | ||
| app-staging-1 | 1 | 2 | 8 ГБ | 50 ГБ SSD | отдельная сеть |
| PostgreSQL staging | 1 | 2 | 8 ГБ | 50 ГБ SSD | отдельная сеть |
Сеть
- Балансировщик → app-1: TCP 8300. app-1 → PostgreSQL: 6432 (TLS). ops-1 → app-1: метрики.
- Исходящий трафик app-1 — только через NAT-шлюз.
- Прод и staging — разные сети без связности.
Почему так
- Управляемая БД на 2 хостах защищает от части отказов; асинхронная реплика может потерять последние записи. Цели переключения ≤ 5 мин и PITR 14 дней нужно подтвердить поставщиком и испытаниями.
- Асинхронная реплика может отставать. Сверка с Paystack помогает найти внешний платёж, но не восстанавливает потерянные параметры заказа. При синхронной схеме запись может остановиться без реплики; выбор доступности и сохранности требует явного решения. Поведение конкретного управляемого сервиса нужно подтвердить.
- Один сервер приложения: целевой срок пересоздания из образа ≤ 30 мин проверяется учениями. Балансировщик позволяет заменить backend без смены DNS.
- Фото в S3 — обязательно: локальный диск app-1 пропадёт вместе с ним.
Целевой регламент ручного разбора оплат
Кнопки ниже — требование к будущему рабочему месту, не подтверждение реализованного экрана. Неизвестный исход оплаты не приравнивается к отказу или отмене.
| Сигнал | Возможная причина | Действие оператора |
|---|---|---|
| Оплата pending > 30 мин | ожидание провайдера или недоставленный webhook | проверить статус, reference, сумму и валюту у Paystack; зачислить только подтверждённый успех. Не отменять финансово неизвестную операцию; повтор сверки безопасен |
| Списано в Paystack, у нас нет записи | авария при переключении БД | зачислить вручную по reference из ежедневной сверки с выпиской |
| Поездка завершена, расчёт не прошёл | сбой между шагами | «Довести расчёт» (идемпотентно) |
| Удержание без связанного заказа или принятия | повреждённые или старые данные | проверить связь и историю; снять только подтверждённое лишнее удержание. Принятие без водителя само по себе не ошибка |
| Расхождение сверки учёта | ошибка кода или данных | эскалация разработчику; определить затронутые операции и возможность их безопасного продолжения |
Частота случаев и время ручного разбора пока не измерены; штат сопровождения и SLA нельзя рассчитывать как на подтверждённые «единицы случаев в месяц».
Алерты
/healthz · 5xx > 1% за 5 мин · переключение мастера · отставание реплики > 30 с · диск > 75% · не прошёл ночной бэкап · оплата pending > 30 мин · расхождение ежечасной сверки.
Доработки кода сверх общих
- Админ-экран «проблемные оплаты и заказы» с кнопками из регламента.
- Ежечасная сверка бухгалтерии (
billing.Reconcileуже написан, не вызывается) и ежедневная сверка с выпиской Paystack. - Фото в объектное хранилище; подключение к БД по имени кластера с переподключением.
- Образ и конфигурация app-1 кодом (Terraform или скрипт).
Энтерпрайз: ни одного потерянного заказа и платежа
Приложение и база дублируются по зонам. Цель — сохранить подтверждённый заказ и внутреннюю запись платежа при покрываемом отказе узла или зоны: нужны синхронная репликация и безопасное переключение лидера. Переключение базы может прервать приём запросов. Отказ всего региона, результат внешней оплаты и восстановление зависших операций проверяются отдельно; копии во втором регионе сами по себе не дают RPO=0.
| Сервер | Количество | Назначение |
|---|---|---|
| Балансировщик | 1 (в 3 зонах) | вход для всех пользователей, переключение между серверами |
| Серверы приложения | 2 | разные зоны; каждый должен выдерживать полный принимаемый профиль — это проверяется при отказе второй копии |
| База данных | 3 | заказы и деньги в трёх зонах; запись подтверждается двумя |
| Сервер эксплуатации | 1 | мониторинг, оповещения, бэкапы, сверки, проверка восстановления |
| Сервер доступа | 1 | единственный вход инженеров к серверам |
| Хранилища | 3 | фото; бэкапы во втором регионе; журналы |
| Тестовый стенд | 3–4 | уменьшенная копия прода для проверки релизов и аварий |
Назначение: договоры с проверенным SLA. Сценарий роста до 1 000+ машин требует отдельного измерения и не является подтверждённым пределом этой конфигурации.
Схема
flowchart TB
U([Пользователи и вебхуки Paystack]) -->|HTTPS · WebSocket| LB[L7-балансировщик · 3 зоны · TLS]
LB --> A1
LB --> A2
subgraph ZA[Зона A · регион 1]
A1[app-1
parkmanager · OSRM]
P1[(pg-1 мастер)]
end
subgraph ZB[Зона B · регион 1]
A2[app-2
parkmanager · OSRM]
P2[(pg-2 реплика)]
end
subgraph ZC[Зона C · регион 1]
P3[(pg-3 реплика)]
OPS[ops-1 · мониторинг · бэкапы]
end
A1 --> P1
A2 --> P1
P1 ==>|синхронно| P2
P1 ==>|синхронно| P3
A1 --> NAT[NAT-шлюз · статический IP]
A2 --> NAT
NAT --> EXT([Paystack · карты · AirLabs])
OPS --> BK[(Регион 2 · S3 бэкапы · WORM)]
Спецификация
| Узел | Кол-во | vCPU | RAM | Диск | Сеть / размещение |
|---|---|---|---|---|---|
| L7-балансировщик | 1 | managed, узлы в 3 зонах; HTTP/2, WebSocket, idle ≥ 120 с, drain ≥ 30 с; ≥ 1 000 RPS, ≥ 2 000 WS | публичный IP, DDoS-защита облака | ||
| app-1, app-2 | 2 | 4, 100% | 16 ГБ | 50 ГБ SSD, ≥ 2 000 IOPS | зоны A и B, только приватный IP |
| PostgreSQL (managed) | 3 | 4, 100% | 16 ГБ | 200 ГБ SSD, ≥ 6 000 IOPS, ≥ 200 МБ/с | зоны A, B, C; синхронная/кворумная репликация; PITR 30 дней |
| ops-1 | 1 | 2 | 8 ГБ | 200 ГБ SSD | зона C |
| bastion-1 | 1 | 2, 20% | 2 ГБ | 20 ГБ | зона C, публичный IP, SSH по ключам / WireGuard |
| NAT-шлюз | 1 | managed | статический IP для белых списков Paystack | ||
S3 pm-prod-media | 1 | версионирование, удаление фото смен старше 180 дней | регион 1, приватный, подписанные ссылки | ||
S3 pm-prod-backup | 1 | WORM / Object Lock 35 дней, хранение 90 дней, шифрование | регион 2, другой аккаунт | ||
S3 pm-prod-logs | 1 | хранение 90 дней | регион 1 | ||
| Staging | 3–4 | 2 | 8 ГБ | 50 ГБ SSD | 1–2 app + PostgreSQL на 2 хостах; отдельная сеть |
Сеть и доступы
- Одна VPC на окружение, подсети в каждой зоне; прод и staging без связности.
- Правила: балансировщик → app 8300; app → pg 6432 (TLS); ops → app метрики; ops → реплика pg; bastion → всё 22; остальное запрещено.
- Публичные IP — только у балансировщика, NAT-шлюза и bastion.
- Секреты — в менеджере секретов облака; удаление кластера БД и бакета бэкапов — только с двумя подтверждениями.
- DNS у управляемого провайдера, TTL 60 с, CAA-запись.
SLO
| Показатель | Цель | Механизм |
|---|---|---|
| Доступность | ≥ 99,9% / месяц | N+1 по приложению и зонам; rolling-деплой |
| RPO заказов и денег | 0 | synchronous_commit=on, кворум ANY 1 из двух реплик в других зонах |
| RTO отказ app | цель — без общего простоя; запрос в отказавший узел может потребовать повтора | вторая копия уже в ротации; health-check 5 с, вывод после 2 неудач |
| RTO отказ мастера БД | ≤ 5 мин | автопереключение, подключение по имени кластера |
| RTO потеря региона | ≤ 4 ч | восстановление из S3 второго региона; учения раз в квартал |
| p95 API | ≤ 300 / 500 мс | запас ×3 по мощности |
Почему каждый узел
- 3 хоста БД позволяют спроектировать синхронную запись при недоступности одной реплики. Нужно подтвердить независимость зон, правила подтверждения записи, безопасного выбора лидера и защиты от двух лидеров; read-реплика сама по себе не доказывает эту схему.
- Каждый app-сервер должен выдерживать 100% профиля — проверить нагрузку оставшейся копии при отказе второго узла.
- Балансировщик managed — своя VM-балансировщик сама стала бы единой точкой отказа.
- Бэкапы в другом аккаунте с WORM — защита от ошибки человека и компрометации аккаунта, а не только от отказа железа.
- ops-1 отдельно — его отказ не влияет на приём заказов.
Доработки кода — без них железо не даёт RPO = 0
- Статус, деньги и обязательное событие — в одной транзакции; этот механизм реализован в текущем рабочем дереве. При выпуске нужна проверка конкретной ревизии, а не повторное обещание будущей разработки.
- Защита повторов создания заказа и пополнения реализована локально; проверить конкурентные запросы и настоящего провайдера на стенде приёмки.
- Вебхук Paystack: записать → ответить 200 → обработать задачей River; сверка pending-платежей раз в несколько минут.
- «Дворник»:
completedбез расчёта, удержание без назначения, резерв без заказа — доводятся автоматически; ежечасная сверка бухгалтерии и с Paystack. - Выбор лидера (advisory lock) для одиночных тиков: статусы водителей, аренда, симулятор.
- Фото в S3; обратно совместимые миграции (expand → deploy → contract).
- Тесты на сбои: падение процесса на каждом шаге и повтор запроса → ровно один заказ и одно списание.
Процессы
- Деплой: GitHub Actions → staging автоматически → smoke-тесты → ручное подтверждение → прод по одному серверу; откат ≤ 5 мин.
- Учения: восстановление бэкапа — раз в месяц автоматически; переключение мастера и выключение app-сервера — раз в квартал.
- Алерты 24/7:
/healthz, 5xx > 1%, p95 выше SLO, отставание реплики > 10 с или потеря кворума, диск > 75%, не прошёл бэкап, расхождение сверки, pending > 15 мин, застрявшие заказы, неподтверждённые критичные уведомления.
Размещение данных: выбранный старт и подтверждения
Для старта выбран MTN в Нигерии. Географию основных данных, фотографий, журналов и всех резервных копий нужно подтвердить поставщиком и юристом. Azure в ЮАР ниже — историческая альтернатива из анализа 2 октября, не текущая рекомендация и не доказательство уже обеспеченного хранения.
| Площадка | Регионов в Африке | Назначение |
|---|---|---|
| Azure South Africa North (Йоханнесбург) | 1 | основной регион: серверы и база |
| Azure South Africa West (Кейптаун) | 1 | второй регион: бэкапы |
| Дата-центры в Лагосе и Абудже | — | запасной путь, если закон потребует хранить данные в Нигерии |
Кандидаты
Историческая таблица из исходного анализа 2 октября. Число зон, свойства управляемых БД и задержки заново не проверены; для закупки она не заменяет подтверждение поставщика. Выбранный старт — MTN в Нигерии. Основной и резервный регионы и правила хранения данных согласуются отдельно.
| Площадка | Зон | Второй регион в Африке | Управляемый PostgreSQL | До Лагоса |
|---|---|---|---|---|
| Azure South Africa North | 3 | да — South Africa West | Flexible Server, HA со standby в другой зоне | ~90–120 мс |
| AWS af-south-1 (Кейптаун) | 3 | нет | RDS / Aurora | ~100–130 мс |
| Google Cloud africa-south1 | 3 | нет | Cloud SQL | ~90–120 мс |
| ДЦ Лагоса (Rack Centre, Equinix LG1, Digital Realty и др.) | обычно 1 | второй ДЦ в Лагосе или Абудже | как правило нет — свой Patroni | ~5–20 мс |
Требования к площадке
- Все копии данных — в Африке: БД, реплики, бэкапы, фото, логи, снапшоты дисков.
- Исходящий доступ к Paystack и входящие вебхуки Paystack (с текущей российской площадки доступа нет — проверено).
- Для варианта 3 — три зоны доступности в регионе; для вариантов 2–3 — второй регион или ДЦ под бэкапы.
- Договор обработки данных (DPA) с провайдером.
Историческая альтернатива: Azure
- В исходном сравнении рассматривалось облако с несколькими африканскими регионами и зонами. Состав регионов и свойства конкретных сервисов перед заказом нужно проверить заново; это не актуальный каталог поставщиков.
- Прежняя оценка задержки ЮАР → Лагос 90–130 мс не является измерением p95 API. Проверять нужно полный путь с сетевой задержкой и обработкой запроса.
- Свойства синхронного standby, ограничения переключения и область RPO=0 требуют подтверждения выбранного сервиса. Для старта сейчас выбран MTN в Нигерии.
Если закон потребует хранить данные в Нигерии
Облака из ЮАР отпадают. Вариант 3 строится в двух ДЦ Лагоса и одном в Абудже: PostgreSQL на Patroni с синхронной репликацией (3 VM), свой балансировщик в паре (keepalived), S3-совместимое хранилище ДЦ или MinIO. Задержка лучше (5–20 мс), но эксплуатация заметно дороже и требует своего дежурства.