Skip to content

Облачная стратегия — Hetzner-first, AWS по триггеру

Стартуем полностью на Hetzner. Managed-сервисы AWS подключаем позже, по одному, только когда конкретный сигнал масштаба или надёжности делает managed-версию стоящей своей наценки. Это решение про деплой, а не про архитектуру — каждый облачно-специфичный концерн уже спрятан за gateway/драйвером, поэтому «перенести в AWS» — это свап, а не переписывание.

Где на самом деле находится P0

Ничто из написанного ниже не отменено — стратегия в силе, и установка по-прежнему на 100% на Hetzner в части компьюта. Две строки таблицы швов ушли вперёд, и обе — в сторону от AWS, а не к нему:

  • KEK секретов больше не написанный руками Kubernetes Secret. Он лежит в HashiCorp Vault на control-кластере и попадает в api через External Secrets Operator (Agentfy/gitops, helm/agentfy-api/values.dev.yamlsecrets.vaultKey: dev/agentfy-api). Триггер на KMS в P3 не изменился — изменилось то, что KMS заменил бы: теперь это Vault.
  • Объектное хранилище решено в пользу Hetzner: terraform/storage.tf создаёт по одному приватному версионируемому бакету на контур, а AWS S3 остаётся только под состояние Terraform и бэкапы. Сторона кода не догнала: единственный драйвер хранилища в этом репозитории пишет в локальный путь.

Какой репозиторий что объявляет: Два репозитория.

Тезис: владеем компьютом, арендуем надёжность

Весь смысл Agentfy.ai 2.0 — дешёвый эфемерный компьют: агент это строка в БД, рантайм это k8s-Job, который скейлится в ноль. Эта экономическая модель работает только на ценах уровня Hetzner; гонять бёрстовые агентские Job'ы на EKS + EC2 её бы уничтожило. Поэтому:

  • Компьют, k8s, worker-Job'ы (вкл. их браузер in-pod), egress → остаются на Hetzner бессрочно. Именно здесь живёт ~10× преимущество Hetzner по цена/производительность, и именно это та нагрузка, что масштабируется.
  • AWS подключаем только для managed-состояния, durability, ключей и доставляемости — там, где надёжность/комплаенс AWS действительно стоят оплаты — и только когда self-host этого одного куска становится узким местом или on-call-обязательством.

Мы арендуем надёжность (managed-failover Postgres, HSM-ключи KMS, durability S3, доставляемость SES) выборочно; мы владеем компьютом, который определяет нашу маржу.

Почему стартуем на Hetzner

  • Стоимость — ~10× дешевле компьют + egress; маржа на pre-revenue и early-revenue выживает.
  • EU / GDPR — данные остаются в EU; co-located кластер с низкой латентностью.
  • Простота — один k3s-кластер, один счёт, без разрастания IAM/VPC, пока продукт ещё движется.
  • Уже абстрагировано — кодовая база изолирует каждый облачный концерн за интерфейсом, поэтому старт только на Hetzner ничего не стоит нам в будущей опциональности (см. следующий раздел).

Шов, который делает это безопасным

По соглашениям CleanSlice внешние системы — это адаптеры/сабмодули за gateway (драйверы infra и gateway'и system). У каждого облачно-сменяемого концерна ровно одна точка свапа:

КонцернИнтерфейс / шовДефолт Hetzner (MVP)Опция AWS (позже)
Object storageдрайвер infra/storage (S3 API)Hetzner Object Storage / R2S3
KEK секретовsecret gateway system (wrap/unwrap)KEK в k8s SecretKMS (заворачивает только DEK)
EmailIEmailGateway в notification/emailResendSES
Реляционное/векторное состояниеinfra/prismaself-host Postgres (pgvector + AGE)RDS/Aurora (только app-данные)
LLMgateway system/llmClaude API (внешний — никогда AWS Bedrock)

Поскольку каждый — это одна реализация за стабильным интерфейсом, миграция это новый драйвер + перенос данных + переключение конфига — никогда не рефакторинг. Поэтому мы можем безопасно отложить всё это.

Фазы и триггеры

Полосы грубые и сигнал-ориентированныесигнал это то, что триггерит переход, а число юзеров лишь полоса, где этот сигнал обычно появляется. Не мигрируем по числу; мигрируем по боли.

ФазаГрубая полосаСигнал, который её открываетЧто меняется
P0 — Launch0 → ~1k юзеров / pre-PMFвыкатка MVP100% Hetzner. Self-host всего; Resend; KEK в k8s Secret; Hetzner OS.
P1 — Traction~1k → 10k / первая выручкаops-рутина на одном компоненте превышает его ценностьПодключаем дешёвые managed-удобства, снимающие рутину: object storage → S3/R2, если нужны CDN/durability SLA; email → SES, если объём/доставляемость требуют. Компьют остаётся на месте.
P2 — Scale & SLAs~10k → 100k / платные SLA, on-call-больself-host stateful-систем становится узким местом/рискомПереносим app Postgres → RDS/Aurora ради автоматического HA-failover + PITR + read-реплик. LightRAG/AGE Postgres держим self-host (managed PG блокирует расширение AGE).
P3 — Enterprise / compliance / global100k+ / SOC2, enterprise, multi-regionтребования комплаенса или глобальной латентностиKMS для HSM-бекового KEK + аудируемая ротация; managed vector/graph на огромном масштабе (OpenSearch / Neptune / Qdrant Cloud); multi-region-чтения.

Что остаётся на Hetzner — навсегда

Это не кандидаты на миграцию; перенос их в AWS поднял бы стоимость, не покупая нужной нам надёжности:

  • k3s-кластер, пул core (api/app/admin/LightRAG).
  • Пул workers + эфемерные worker-Job'ы (с headless-браузером in-pod) — чувствительная к стоимости, scale-out нагрузка.
  • Egress / трафик — плоский, щедрый egress Hetzner против metered egress AWS — решающий рычаг маржи.
  • Redis (очередь/pub-sub/локи) — дёшево self-host'ить; managed только если ops Redis когда-либо начнут доминировать.

Что может мигрировать, и ровно когда

КомпонентДефолтМигрируем в AWS, когда…Дверь в одну сторону?
Object storageHetzner OS / R2 (S3-совместимо)нужны CDN, multi-region или контрактные durability/комплаенсНет — оба говорят на S3 API; синк бакета + переключение конфига.
EmailResendстоимость на письмо доминирует на больших объёмах, либо доставляемость/репутация требуют SESНет — свап IEmailGateway + DNS-записи.
App Postgresself-host (CNPG)нужны автоматический failover + PITR + раздача read-реплик и DBA-рутина > managed-счётаМягко — переключение через логическую репликацию; планируй maintenance-окно. Сначала вынеси LightRAG/AGE PG.
KEK секретовk8s SecretSOC2/enterprise требуют HSM-бекованных ключей + аудируемой ротацииНет — значения остаются в PG; перезаворачиваем DEK, бампаем kekVersion.
Vector / graph (огромный масштаб)pgvector + AGEодна база перерастает pgvector/AGE (сначала бенчмарк)Мягко — пере-эмбеддинг/перестройка индексов (производные данные, не мигрируются).

Оговорка, которая формирует P2: graph-стор LightRAG требует Apache AGE, который managed Postgres (RDS/Neon) не разрешает. Поэтому в момент переноса app-данных на RDS у тебя уже два Postgres (app на RDS, LightRAG/AGE self-host) — либо переноси граф на Neo4j Aura. Реши это на P2, а не случайно.

Механика миграции (почему каждое переключение низкорисковое)

  • Storage: Hetzner OS и S3/R2 — все S3-API → rclone/lifecycle-синк + меняем один конфиг драйвера
    • env. Без изменения кода приложения.
  • Email: реализуем IEmailGateway для SES, верифицируем домен/DKIM, флипаем биндинг. Откат = флипнуть обратно.
  • KEK → KMS: secret gateway заворачивает/разворачивает DEK; KMS меняет лишь как DEK заворачивается. Зашифрованные значения остаются в Postgres нетронутыми; перезаворачиваем под новым kekVersion, старый держим для расшифровки на время ролловера.
  • Postgres → RDS: стандартное переключение через логическую репликацию/pg_dump за infra/prisma; схема и приложение идентичны. Вынеси базу AGE/LightRAG до переноса.
  • Vector/graph: индексы производные — никогда не «мигрируются». Поднимаем новый бэкенд и пере-эмбеддим из исходного markdown/документов; флипаем ретрив, когда догнали.

Замечание про стоимость

Hetzner держит фиксированную инфра-стоимость низкой на P0–P1, пока выручка тонкая. Каждое подключение AWS — это осознанный размен денег на managed-надёжность в точке, где надёжность стоит больше, чем кэш — никогда не дефолт. Счёт растёт вместе с обязательствами (SLA, комплаенс), а не впереди них.

Гардрейлы (non-goals)

  • Не пре-мигрируем. Ни один сервис AWS не заходит до того, как его сигнал-триггер станет реальным. Опциональность уже сохранена швом gateway — покупать её рано лишь добавляет стоимость и IAM/VPC-поверхность.
  • Не переносим компьют в AWS. Экономика эфемерного агента зависит от компьюта и egress по ценам Hetzner. AWS — для managed состояния/ключей/durability, не для гонки агентских Job'ов.
  • Считаем каждую миграцию обратимой, пока не доказано иное (таблица помечает мягкие двери в одну сторону); держим путь Hetzner запускаемым для отката на всё время перехода.

См. также