Choosing a runtime
AWS gives you several places to run code. They differ in one main way: how much of the machine AWS manages for you, and so how much you decide yourself. Every one of them runs the same kind of Alchemy program, takes the same bindings, and gets its IAM role from them.
The same program on every runtime
Section titled “The same program on every runtime”Whichever you pick, you declare it with an id, its configuration and an Effect. Construction binds what it uses, and the handlers it returns do the work. Here it is as an ECS Service:
const api = yield* AWS.ECS.Service( "Api", { cluster, main: import.meta.url, port: 3000, loadBalancer: true }, Effect.gen(function* () { const getObject = yield* AWS.S3.GetObject(Files); return { fetch: Effect.succeed(HttpServerResponse.text("Hello from ECS!")), }; }).pipe(Effect.provide(AWS.S3.GetObjectHttp)),);The same Effect, with its bindings and its fetch, runs as a Lambda Function or on EC2.
So moving part of an app from one runtime to another changes its declaration, not its code. Choose by how the work behaves, and change your mind later if it behaves differently than you expected.
Lambda Functions: run per invocation
Section titled “Lambda Functions: run per invocation”A Lambda Function runs when something invokes it: a request, a queue message, a new object, a schedule. AWS starts environments as invocations arrive and stops them when they don’t, so an idle Function costs nothing and a busy one scales with no setup.
That makes it an easy and cheap place to start. Its limits come from the same model: an invocation runs for at most 15 minutes, each environment handles one invocation at a time, and a new environment takes a cold start before its first one.
Choose it for event handlers, background jobs, scheduled work, and APIs that see uneven traffic.
Lambda Web Functions: HTTP servers on Lambda
Section titled “Lambda Web Functions: HTTP servers on Lambda”A Lambda Web Function runs an HTTP server on Lambda. One environment serves many requests at once, up to 128, so a spike starts fewer environments and requests share warm connections. Responses stream as your handler produces them.
It only receives HTTP, runs Node.js, and has a fixed 2 GB of memory per environment. Choose it for APIs and websites, and pair it with a Lambda Function when the API hands work to a queue.
ECS: containers that keep running
Section titled “ECS: containers that keep running”ECS runs your program as a container on Fargate, and keeps it running. There’s no time limit and no cold start per request, and the program can hold connections, WebSockets or in-memory state for as long as it’s up.
You pay for running tasks whether or not they’re busy. They run inside a VPC: your account’s default one to start, or one you build with the Network helper. Alchemy builds the image from your program, or from a Dockerfile, and pushes it for you.
Choose it for long-lived servers, workers that hold connections open, and anything that already ships as a container.
EKS: Kubernetes
Section titled “EKS: Kubernetes”EKS runs a Kubernetes cluster, with AWS managing the control plane and, in Auto Mode, the nodes. You deploy Deployments, Jobs, Helm charts and raw manifests from the same Stack, with the same bindings.
A cluster takes about ten minutes to create and costs money while it exists. Choose it when you want Kubernetes itself: its tools, its operators, or a team that already runs on it.
EC2: the whole machine
Section titled “EC2: the whole machine”EC2 gives you a virtual machine. You pick the instance type, the operating system and the disk, and you own patching and recovery. Alchemy can run your program on it directly, or leave it as a plain machine.
Choose it for GPUs, custom daemons, software that expects a host, or steady load where a reserved machine is cheapest.
- type
- g5.xlarge · 1 GPU
- image
- your OS and disk
- you own
- patching, restarts, recovery
Mix runtimes in one app
Section titled “Mix runtimes in one app”An app rarely needs just one. A common shape is a Web Function for the API, a Lambda Function consuming the queue it writes to, and an ECS service for the one process that must stay connected:
Each runtime has its own role, written by its own bindings, so each part of the app can reach only what it uses.