Task
Source:
src/AWS/ECS/Task.ts
A Fargate task definition with a container image from one of three sources, declared flat on the props:
main— bundle an inline Effect program into a generated image (compose withimageor an inlinedockerfileto pick the environment; defaults tooven/bun:1).context— build your own Dockerfile (dockerfileis a path relative to the cwd, defaulting to${context}/Dockerfile).image— run a pre-built registry image, mirrored into ECR.
Task provisions task + execution IAM roles, a CloudWatch log group, and
an ECR repository holding the built (or mirrored) image, then registers a
Fargate task definition. Each reconcile registers a new immutable
revision. A launched task runs until its process exits — it is the target
of AWS.ECS.RunTask / StopTask bindings and AWS.ECS.Schedule;
effectful impls return { run }, executed to completion when the
container starts.
Beyond the primary container you can declare task-level configuration
(volumes, runtime platform, ephemeral storage, IPC/PID mode, placement
constraints) and append additional sidecars for multi-container tasks.
Creating a Task
Section titled “Creating a Task”Remote Image
const migrate = yield* Task("DbMigrate", { image: "public.ecr.aws/docker/library/busybox:stable", command: ["sh", "-c", "echo done"], cpu: 256, memory: 512,});Build Your Own Dockerfile
const render = yield* Task("RenderJob", { context: "./render", // dockerfile defaults to ./render/Dockerfile dockerfile: "./render/Dockerfile.gpu", // always a PATH cpu: 1024, memory: 4096,});Inline Effect Program
const drainer = yield* Task( "QueueDrainer", { main: import.meta.url, image: "oven/bun:1", cpu: 256, memory: 512 }, Effect.gen(function* () { const receive = yield* AWS.SQS.ReceiveMessage(queue); return { run: Effect.gen(function* () { // runs to completion, then the container exits const batch = yield* receive({ MaxNumberOfMessages: 10 }); }), }; }),);Multi-Container Tasks
Section titled “Multi-Container Tasks”const task = yield* Task("ApiTask", { main: import.meta.url, port: 3000, sidecars: [ { name: "otel-collector", image: "public.ecr.aws/aws-observability/aws-otel-collector:latest", essential: false, portMappings: [{ containerPort: 4317, protocol: "tcp" }], }, ],});Bundling & Tree-shaking
Section titled “Bundling & Tree-shaking”main is bundled with rolldown at deploy time. Top-level calls in the
effect, @effect/*, alchemy, @alchemy.run/*, and
@distilled.cloud/* packages receive #__PURE__ annotations by
default, so anything the task doesn’t use from those packages is
tree-shaken out of the bundle. Any other package — including your own
app — is left untouched unless you list it explicitly.
Treat additional packages as pure
Pass package names (or picomatch globs) via build.pure.packages to
annotate them in addition to the defaults.
{ main: import.meta.url, build: { pure: { packages: ["my-lib", "@my-scope/*"] }, },}Listing a package annotates calls whose result is bound (variable
initializers, exports) — safe anywhere. If a listed package also
declares "sideEffects": false (or []) in its package.json, that
combination opts it into full annotation: top-level calls whose result
is discarded (e.g. router.on("/path", handler) registrations) are
also marked pure and deleted under minification when unused. Only list
a sideEffects: false package if its modules really are free of
meaningful top-level side effects. The effect, alchemy, and
@distilled.cloud defaults declare exactly that, on purpose — their
modules are designed to be fully tree-shakeable.
Disable pure annotations
{ main: import.meta.url, build: { pure: false },}Task-Level Configuration
Section titled “Task-Level Configuration”ARM64 with EFS Volume and Ephemeral Storage
const task = yield* Task("WorkerTask", { main: import.meta.url, runtimePlatform: { cpuArchitecture: "ARM64", operatingSystemFamily: "LINUX" }, ephemeralStorage: { sizeInGiB: 40 }, volumes: [ { name: "data", efsVolumeConfiguration: { fileSystemId: fileSystem.fileSystemId }, }, ], container: { mountPoints: [{ sourceVolume: "data", containerPath: "/data" }], },});Environment Files from S3
const task = yield* Task("ApiTask", { main: import.meta.url, environmentFiles: [ { value: "arn:aws:s3:::my-config-bucket/app.env", type: "s3" }, ],});