Saltar al contenido principal

ADR 031 — One customer compute answer: ECS Fargate; EKS path frozen

Context​

Go-live §F-6 demanded we "pick and finish ONE client compute answer". Two candidates existed:

  1. ECS Fargate (minimum-tier pattern). The hosted minimum tier already runs api/admin/ui/ide on ECS Fargate with a proven task-definition / Secrets-Manager-injection / ALB pattern, and customer_account_aws already provisions an ECS cluster placeholder in every customer account.
  2. EKS (infrastructure/envs/dev). EKS 1.32 + Karpenter + ESO + ArgoCD — never applied end-to-end, and the aws Kubernetes overlay (gp3 StorageClasses, ALB/NLB ingress, IRSA annotations, ExternalDNS) does not exist. Until one path is exercised, "the 76-service topology on client AWS" is fiction.

Running both forks means two secret-delivery mechanisms (SM→ECS vs ESO), two ingress models, two license-delivery stories (env-file vs CSI), and double the unproven surface at exactly the moment the program needs one honest answer.

Decision​

ECS Fargate is the one customer compute answer. The §F-5 workload plane is built into terraform/modules/customer_account_aws (workloads.tf, Default-OFF behind enable_workload_plane):

  • api + Celery worker (light/coordination queues: default,paper,terraform,ingestion,workflows) + beat (pinned singleton, min-healthy 0% / max 100%) as Fargate services on the existing KB-silo cluster, consuming the module's workload_env contract;
  • ElastiCache Redis broker with a Terraform-minted AUTH token auto-filled into Secrets Manager (the minimum-tier idiom);
  • services depends_on the F-2 migration gate — no workload converges onto an unmigrated schema;
  • license lease + public key delivered as Secrets Manager → ECS secrets env injection, written to the ALPHASWARM_LICENSE_*_PATH files by an sh -c command preamble (every runtime image ships ENTRYPOINT []). No CSI driver, no sidecar, no in-plane renewal daemon;
  • rollouts are governed Terraform applies pinned to app_version through the One Gate — deliberately no ignore_changes on task definitions (the task-def diff is the release-review artifact), diverging from the hosted minimum tier where CI rolls task definitions out-of-band.

The EKS path is frozen, not deleted. infrastructure/envs/dev stays in the tree as authored reference; no aws k8s overlay will be written, and enable_secrets_module/enable_eso stay off for customer targets. Freezing (rather than deleting) preserves the option to thaw for a future customer whose contract mandates Kubernetes — at which point the missing overlay and an OpenBao/ESO story must be built and exercised end-to-end before it may be called an answer.

Consequences​

  • One secret-delivery mechanism (Secrets Manager → ECS injection), one ingress model (optional ALB behind enable_workload_ingress + the §A-1.4 ACM certificate), one license story.
  • Queue honesty: the plane drains the light queues + beat. Heavy queues (backtest,training,ml,agents,factors,rag), ml.control, hft, lab.cpu, and legacy ingest are undrained — hft/lab.cpu/ingest are undrained on every target today (parity, not regression); the heavy-queue executor service is a named defer.
  • License renewal in ECS is out-of-band: re-seed the secret, then force a new deployment (see the license runbook). Leases expire into grace then 403 otherwise.
  • Nothing here is applied anywhere yet: CI proof is fmt + validate + mock-provider terraform test plans (the only CI-side count-path evaluation — terraform validate never evaluates count paths). First real proof is a governed plan/apply in a sandbox customer account.
  • Anyone proposing customer EKS must supersede this ADR first.