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-стану, довговічності, ключів і доставлюваності — там, де надійність/комплаєнс AWS справді варті оплати — і лише коли self-host цього одного шматка стає вузьким місцем чи on-call-тягарем.

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

Чому стартуємо на Hetzner

  • Вартість — ~10× дешевший компют + egress; маржа на pre-revenue та ранньому revenue виживає.
  • EU / GDPR — дані лишаються в EU; co-located кластер з низькою latency.
  • Простота — один 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 — Запуск0 → ~1k юзерів / pre-PMFвідвантаження MVP100% Hetzner. Self-host усього; Resend; KEK у k8s Secret; Hetzner OS.
P1 — Тракшн~1k → 10k / перший revenueops-рутина одного компонента перевищує його цінністьВпроваджуємо дешеві managed-зручності, що знімають рутину: object storage → S3/R2, якщо потрібні CDN/SLA довговічності; email → SES, якщо цього вимагають обсяг/доставлюваність. Компют лишається на місці.
P2 — Масштаб і SLA~10k → 100k / платні SLA, on-call-більself-host stateful-систем стає вузьким місцем/ризикомПереносимо app-Postgres → RDS/Aurora заради автоматичного HA-failover + PITR + read-репліки. Postgres LightRAG/AGE лишаємо self-host (managed PG блокує розширення AGE).
P3 — Enterprise / комплаєнс / global100k+ / SOC2, enterprise, multi-regionвимоги комплаєнсу чи глобальної latencyKMS для HSM-backed KEK + аудитована ротація; managed vector/graph на величезному масштабі (OpenSearch / Neptune / Qdrant Cloud); multi-region-читання.

Що лишається на Hetzner — назавжди

Це не кандидати на міграцію; перенесення їх в AWS підняло б вартість, не купуючи надійності, яка нам потрібна:

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

Що може мігрувати, і саме коли

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

Застереження, що формує P2: граф-сторедж LightRAG потребує Apache AGE, який managed Postgres (RDS/Neon) не дозволяє. Тож щойно app-дані переїжджають на RDS, ти вже ганяєш два Postgres (app на RDS, LightRAG/AGE self-host) — або переносиш граф на Neo4j Aura. Вирішуй це на P2, а не випадково.

Механіка міграції (чому кожен cutover низькоризиковий)

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

Зауваження про вартість

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

Запобіжники (non-goals)

  • Не пре-мігруй. Жоден AWS-сервіс не заходить до того, як його тригер-сигнал стане реальним. Опціональність уже збережена шовом gateway — купувати її рано лише додає вартість і IAM/VPC-поверхню.
  • Не переноси компют в AWS. Економіка ефемерного агента залежить від компюту й egress за цінами Hetzner. AWS — для managed-стану/ключів/довговічності, не для ганяння агентних Job-ів.
  • Розглядай кожну міграцію як зворотну, поки не доведено протилежне (таблиця позначає мякі one-way-двері); тримай шлях Hetzner запускним для rollback упродовж переходу.

Див. також