| 1 | --- |
| 2 | title: Choosing a runtime |
| 3 | description: Lambda vs ECS vs EKS vs EC2 for Alchemy apps — cold starts, cost shape, packaging, and how much of each Alchemy currently covers. |
| 4 | --- |
| 5 | |
| 6 | Every Alchemy app on AWS needs somewhere for its code to run. |
| 7 | Alchemy ships four runtimes, all driven by the same pattern — |
| 8 | bundle an Effect program, deploy it as a resource, bind building |
| 9 | blocks to it: |
| 10 | |
| 11 | - **Lambda** — serverless functions. **Use this by default.** |
| 12 | - **ECS** — long-running containers on Fargate. |
| 13 | - **EKS** — containers as Kubernetes workloads on a managed |
| 14 | Auto Mode cluster. |
| 15 | - **EC2** — virtual machines you fully control. |
| 16 | |
| 17 | ## At a glance |
| 18 | |
| 19 | | | Lambda | ECS | EKS | EC2 | |
| 20 | | ---------------- | ------------------------------------------ | ------------------------------------------ | -------------------------------------------- | ---------------------------------------- | |
| 21 | | Execution model | Per-request, event-driven | Always-on containers | Kubernetes objects (Deployments, Jobs) | Always-on machine | |
| 22 | | Cost shape | Pay per invocation; scales to zero | Pay per running task | Control plane + Auto Mode nodes | Pay per running instance | |
| 23 | | Startup | Cold starts (ms–s), then warm | Task launch (tens of seconds), then steady | Cluster create (~10 min), Pods in seconds | Instance boot (minutes), then steady | |
| 24 | | Packaging | Bundled zip (Rolldown) | Docker image, built + pushed for you | Docker image, built + pushed for you | Bundled program on an AMI you choose | |
| 25 | | Networking | None required (Function URL) | VPC required (awsvpc), optional ALB | VPC required, `LoadBalancer` Services | VPC required, you own every primitive | |
| 26 | | Alchemy coverage | Fully documented | Cluster/Service/Task resources | Cluster/Deployment/Job/Manifest/Helm | Instance + full VPC primitives | |
| 27 | |
| 28 | ## Lambda — the default |
| 29 | |
| 30 | Serverless, event-driven, and the runtime this documentation is |
| 31 | written around. You get the [`Function`](/providers/aws/lambda/function) |
| 32 | resource with a public Function URL, typed bindings that mint |
| 33 | least-privilege IAM policies from your call sites, and |
| 34 | `Stream`-shaped event sources for SQS, Kinesis, DynamoDB |
| 35 | Streams, S3 notifications, SNS, and EventBridge. Cold starts and |
| 36 | the 15-minute execution cap are the trade; per-request pricing |
| 37 | and zero idle cost are the payoff. |
| 38 | |
| 39 | Choose Lambda unless you have a specific reason not to. |
| 40 | |
| 41 | → [Lambda](/aws/compute/lambda) |
| 42 | |
| 43 | ## ECS — long-running containers |
| 44 | |
| 45 | When your workload doesn't fit a request/response window — a |
| 46 | WebSocket server, a worker that holds connections open, anything |
| 47 | that should be always-on — run it as a container. Alchemy models |
| 48 | ECS with three resources: |
| 49 | |
| 50 | - [`Cluster`](/providers/aws/ecs/cluster) — an ECS cluster for |
| 51 | running tasks and services. |
| 52 | - [`Task`](/providers/aws/ecs/task) — bundles an inline Effect |
| 53 | program, builds and pushes a Docker image to a generated ECR |
| 54 | repository, provisions task + execution IAM roles and a |
| 55 | CloudWatch log group, and registers a Fargate task definition. |
| 56 | Tasks can serve HTTP directly and accept the same |
| 57 | binding contract (env + IAM policy statements) as Lambda. |
| 58 | - [`Service`](/providers/aws/ecs/service) — keeps a task |
| 59 | definition running with awsvpc networking; set `public: true` |
| 60 | and Alchemy provisions a public ALB + listener + target group |
| 61 | for you. |
| 62 | |
| 63 | You pay for running tasks whether or not they're serving |
| 64 | traffic, and you bring a VPC (subnets + security groups) — the |
| 65 | [`Network`](/providers/aws/ec2/network) helper builds one in a |
| 66 | single call. |
| 67 | |
| 68 | → [ECS](/aws/compute/ecs) |
| 69 | |
| 70 | ## EKS — when your platform is Kubernetes |
| 71 | |
| 72 | When the workload is container-shaped but you want Kubernetes |
| 73 | itself — Helm charts, operators, raw manifests, or teams already |
| 74 | speaking Deployments and Jobs — Alchemy targets **EKS Auto Mode**, |
| 75 | where AWS manages the control plane, nodes, storage, and |
| 76 | load-balancer integration. Alchemy models it with: |
| 77 | |
| 78 | - [`Cluster`](/providers/aws/eks/cluster) — the control plane; |
| 79 | `compute: "auto"` turns on Auto Mode with sensible defaults. |
| 80 | - [`Deployment`](/providers/kubernetes/deployment) — a replicated |
| 81 | Kubernetes server (the Kubernetes analog of `AWS.ECS.Service`) |
| 82 | with the same three image sources as ECS: a registry `image`, a |
| 83 | Dockerfile `context`, or an inline Effect program via `main`. |
| 84 | - [`Job`](/providers/kubernetes/job) — run-to-completion work, or a |
| 85 | `CronJob` when you set `schedule`. |
| 86 | - [`Manifest`](/providers/kubernetes/manifest) and |
| 87 | [`HelmChart`](/providers/kubernetes/helmchart) — any raw Kubernetes |
| 88 | object or a rendered Helm chart, applied via server-side apply. |
| 89 | |
| 90 | Bindings work the same as on Lambda and ECS — env vars plus IAM |
| 91 | policy statements, delivered through an EKS Pod Identity role — |
| 92 | and there is no YAML and no `kubectl` step. You pay for the |
| 93 | control plane and the nodes Auto Mode provisions, you bring a VPC |
| 94 | (the [`Network`](/providers/aws/ec2/network) helper builds one), |
| 95 | and the control plane takes ~10 minutes to create. |
| 96 | |
| 97 | → [EKS](/aws/compute/eks) |
| 98 | |
| 99 | For ML training fleets specifically — persistent, health-checked |
| 100 | GPU clusters rather than application containers — EKS pairs with |
| 101 | [SageMaker HyperPod](/aws/compute/hyperpod): the HyperPod nodes |
| 102 | join your EKS cluster, and `Deployment`/`Job` opt onto them with |
| 103 | the `hyperpod` prop. |
| 104 | |
| 105 | ## EC2 — when you need the machine |
| 106 | |
| 107 | Full-control VMs for workloads that need an OS, a GPU, custom |
| 108 | daemons, or just predictable dedicated capacity. The |
| 109 | [`Instance`](/providers/aws/ec2/instance) resource can act as a |
| 110 | low-level compute primitive or run a bundled long-lived Effect |
| 111 | program directly on the machine (including serving HTTP), and |
| 112 | Alchemy ships the complete networking toolkit around it: |
| 113 | [`Vpc`](/providers/aws/ec2/vpc), |
| 114 | [`Subnet`](/providers/aws/ec2/subnet), |
| 115 | [`SecurityGroup`](/providers/aws/ec2/securitygroup), NAT and |
| 116 | internet gateways, route tables, EIPs, and VPC endpoints (see |
| 117 | [VPC & networking](/aws/networking)). |
| 118 | |
| 119 | You own patching, scaling, and availability. |
| 120 | |
| 121 | → [EC2](/aws/compute/ec2) |
| 122 | |
| 123 | ## Rule of thumb |
| 124 | |
| 125 | 1. Start with **Lambda**. Per-request cost, no servers, and the |
| 126 | whole documented binding/event-source surface. |
| 127 | 2. Move a workload to **ECS** when it's long-running, needs more |
| 128 | than 15 minutes, or is already a container. |
| 129 | 3. Pick **EKS** over ECS when you want Kubernetes itself — |
| 130 | Helm charts, operators, raw manifests — not just a container |
| 131 | runner. |
| 132 | 4. Reach for **EC2** when you need the machine itself — kernel |
| 133 | access, GPUs, custom networking, or software that expects a |
| 134 | host. |
| 135 | |
| 136 | ## Where next |
| 137 | |
| 138 | - [Lambda](/aws/compute/lambda) — deploy a function with a public URL. |
| 139 | - [AWS overview](/aws) — resources and recipes. |
| 140 | - [Providers reference](/providers) — generated docs for every |
| 141 | ECS, EKS, and EC2 resource. |