Как мы сократили счёт с $800 до €160 — и почти потеряли рассудок (но выжили)

Мы делаем YA — это high-load AI-дневник, который помогает сохранять дни без лишних усилий. Ты фиксируешь мысли, события и настроение в любом формате, а Чат-бот Оракул задаёт короткие вопросы, выделяет главное и показывает инсайты по твоим повторяющимся паттернам. Делается аналитика данных из HealthKit, realtime-агрегациями и собственными AI надстройками. Продукт делали 2 года, в проде — 4 месяца. Активных пользователей с ИИ-фичами сейчас ~40, RPS вырос с 3 до 30–40.

Это история о трёх хостингах, одном CTO-провале сна и нескольких ночных эпических сражениях с Traefik и бэкапами.

Акт I. DigitalOcean — «пока всё помещается»

Начали проект мы просто: один Docker Swarm-узел, несколько droplets, Postgres, Redis, MinIO — и чувство, что «на старте так даже лучше». Счёт ~$400/мес. Радость недолгая.

Получилась как-то раз такая сцена: ночь. Я сижу с чашкой давно остывшего кофе, в телефоне пуш от мониторинга: «IO wait растёт». В логах — строки, похожие на «ну всё, сейчас будет красиво». Проверяю — backup не настроен (тот самый забытый pgbackrest). Мгновение тишины, потом внутренний монолог: «Ладно, копаем дампы, снимки машины, буду руками переносить». В три часа ночи я тащу SQL-дамп по SCP, как недостойный тор мьёльнир, у окна — пустая пачка печенек и строка в терминале: `pg_restore: done`. Спасли — но нерв уже потёрт.

Проблемы были очевидны: CPU не давал нужной отдачи, RAM «вела себя» странно, БД троттлила под нагрузкой — и всё это при росте нагрузки быстро бы переросло в ад.

Акт II. AWS — «мы сделали по-взрослому и переплатили»

Логика была такая: managed-сервисы это меньше забот, больше uptime. Мы переехали на AWS: RDS (3 инстанса), Redis, начальная Kafka, Lambda (1000–3000 вызовов в час), S3, ALB. Результат: комфорт и счёт — $700–950/мес.

Работа шла отлично, все сетки были настроены, авто-масштабирование, CI, канарейки, но спустя пол года: смотрю биллинг в июле — он как ежемесячный счёт за коммуналку, но умноженный на 10.

В онлайн-офисе — короткий разговор с фаундером:

«— Сколько за хостинг? $890?»

«— Видел, нам нравится AWS, но он любит деньги»

«— Ну и что делать?»

Тишина, но понимаю: либо мы сжигаем деньги, либо ищем другой путь.

Как бы плюсы AWS — стабильность и скорость разработки. Но минус — каждый новый managed-сервис добавляет +$ в билл, и в результате выходит что платим облаку зарплату мидла.

Мы сделали анализ, но принять решение вручную оказалось проще — и началась подготовка к дерзкому манёвру.

Акт III. Hetzner — «всё своё и под контролем»

Решение: походить по краю и взять ответственность на себя. Миграция заняла 2–3 дня по 12 часов; один переход дал 8 часов даунтайма. Паника была, но это был контролируемый ад.

Микро-сцена миграции: полночь, меняется DNS, Traefik дергает маршрут — и внезапно часть трафика уходит на стейджинг. В чатике команды — гифка с метнувшимся кабанчиком и сообщение: «Кто переписал маршруты?» Я: «Я» (но без сильной гордости).

Быстро рулю iptables, делаю костыльный перенос через `socat` и молюсь, чтобы не включился cron с очередной рассылкой тестовых писем. В итоге: клиенты не заметили, но я помню запах этого пакета горелых печенек из своей духовки. В какой-то момент я даже подумал взять малинок и купить белый ip, но это прошло как только я поспал.

Что получилось

Архитектура на Hetzner — шесть серверов:

  • 2-3 × 16 vCPU / 32 GB — Docker Swarm (основная нагрузка)
  • 1 × 4 vCPU / 8 GB — Postgres (Pigsty: Patroni, PgBouncer; single-node сейчас, подготовлено под HA)
  • 1 × 4 vCPU / 8 GB — k3s (Kafka + RabbitMQ)
  • 1 лёгкая нода — back-office
  • 1 dev-нода

Итоговый счёт: €140–160/мес — примерно тройная экономия по сравнению с AWS.

Есть даже веселая ситуация про ClickHouse: он появился только на Hetzner. Я запустил single-node ClickHouse, в прикол назвал таблицу `events_big` и увидел, как агрегации по user-story map начали летать быстрее, чем я успевал писать отчёты. Первый «тяжёлый» запрос вернулся за время, которое позволило мне успеть сделать чай. Маленькая победа.

Почему остался Docker Swarm

Я не мастер k8s — и понимаю, что за переходом на Kubernetes придёт гора поддержки, и нервов, и денег. Поэтому:

  • Swarm даёт rolling updates и zero-downtime deploy.
  • Наш autoheal — скрипт, который пингует сервис, и если тот не отвечает — делает `docker restart`. Называем его «лечилка» (иногда иронично — «автохилерша»).
  • k3s используется точечно для Kafka/RabbitMQ, где нужен побольше контроль.

Была ситуация: autoheal в три часа утра перезапустил сервис и спас день само-копания. Я проснулся от пуша с мониторинга, посмотрел журнал и подумал: «Иногда мои утилиты — братья».

Самый жёсткий момент

Переход AWS -> Hetzner дал нам 8 часов downtime: A/B-сервисы начали падать, терялся кэш, фронт играл в «502». Я помню, как в голове одна мысль: «Если сейчас мы всё потеряем — я верну счёт облаку и уйду в монастырь». Но руками всё переложили без критической потери данных. Паника была — но опыт дороже.

Что стало хуже

  • Нервы. Если бы это можно было упаковать в CSV, он бы содержал столбец «кол-во бессонных ночей»
  • Ответственность: всё держится на одном человеке — на мне, собьёт электросамокат и до свидания
  • Риск ошибок: да, были простои и потерянные куски кэша

Однажды я по невнимательности заблокировал порт RabbitMQ на firewall — очередь стояла, а я в это время пил чай и обсуждали в команде UI-фичу. Очередь подкрутилась, когда я вспомнил про `ufw`. С тех пор чай пью быстро и осторожно.

Что бы я сделал иначе

  • Сразу инфраструктурную карту и расчёт точек роста.
  • Не держал бы всё в одном Swarm-контексте.
  • Подготовил бы HA для БД с самого начала (3 ноды).
  • Нанял бы DevOps рано — это сэкономит тысячу нервов.

Итог для тех, кто думает повторить наш путь

Managed == удобство + счёт. Self-hosted == контроль + экономия + бессонные ночи. С экономией €140–160 в месяц нам удалось продлить runway и дать продукту шанс. Но если вы не готовы взять риск и ответственность — подумайте ещё раз.

Мы сэкономили деньги, но я приобрёл 4 года опыта и примерно 10 лет одновременно (шутка). В реальности — это десятки ночей с `scp`, `ansible` и парой крайне нервных коммитов.