JobDefinition
Source:
src/AWS/Batch/JobDefinition.ts
An AWS Batch job definition for Fargate container jobs. Job definitions are immutable revisions — changing the container configuration registers a new revision under the same name (like ECS task definitions); destroying the resource deregisters every active revision.
JobDefinition is a Platform: alongside the low-level container form
(image + executionRoleArn), it supports Effect-native run-to-completion
implementations — an inline Effect program that Alchemy bundles,
containerizes as the job container’s command, pushes to a managed ECR
repository, and registers, provisioning the job and execution roles
automatically. Capability bindings (e.g. S3 GetObject) attach IAM policy
statements to the managed job role and inject their environment variables
into the container.
Creating Job Definitions
Section titled “Creating Job Definitions”Busybox echo job (low-level container form)
const jobDef = yield* Batch.JobDefinition("EchoJob", { image: "public.ecr.aws/docker/library/busybox:latest", command: ["echo", "hello from batch"], executionRoleArn: executionRole.roleArn,});Sized job with environment
const jobDef = yield* Batch.JobDefinition("EtlJob", { image: image.imageUri, vcpus: 1, memory: 2048, environment: { STAGE: "prod" }, jobRoleArn: jobRole.roleArn, executionRoleArn: executionRole.roleArn, retryAttempts: 3, timeout: "15 minutes",});Effect-Native Jobs
Section titled “Effect-Native Jobs”Tagged class with an inline run-to-completion Effect
export default class Nightly extends Batch.JobDefinition<Nightly>()( "Nightly", { main: import.meta.url, vcpus: 1, memory: 2048 }, Effect.gen(function* () { const getObject = yield* AWS.S3.GetObject(bucket); return { run: Effect.gen(function* () { const data = yield* getObject({ key: "input.csv" }); yield* Effect.log("processed nightly batch"); }), }; }),) {}Eager inline job
export default Batch.JobDefinition( "Reindex", { main: import.meta.url }, Effect.succeed({ run: Effect.log("reindex complete"), }),);Plain external script (bundled as-is)
// ./job.ts runs top-level and exits; Alchemy bundles + containerizes it.const jobDef = yield* Batch.JobDefinition("Script", { main: path.join(import.meta.dirname, "job.ts"),});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 job 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 },}