Deployment
Source:
src/Kubernetes/Deployment.ts
A replicated Kubernetes server on any cluster — the Kubernetes analog of
AWS.ECS.Service.
Deployment provisions a Kubernetes Deployment + Service (+
ServiceAccount) via server-side apply, plus — through the target
cluster’s platform adapter — workload identity and a container image
from exactly one of three sources flat on props: main (bundle an
inline Effect program), context (build your own Dockerfile), or
image (a pre-built registry reference). On AWS.EKS.Cluster targets
it accepts the same { env, policyStatements } host binding contract as
AWS.Lambda.Function and AWS.ECS.Task: every AWS Binding.Service
(S3, DynamoDB, SQS, …) attaches env vars to the pod spec and IAM policy
statements to a generated pod-identity role. On registry-less clusters
(Kubernetes.KubeConfig(...)) run pre-built image references and bind
through environment variables.
Creating a Deployment
Section titled “Creating a Deployment”Remote image on EKS (external — no Effect runtime in the container)
const cluster = yield* AWS.EKS.Cluster("Cluster", { compute: "auto" });
const nginx = yield* Kubernetes.Deployment("Nginx", { cluster, image: "nginx:1.27", namespace: "default", replicas: 3, port: 80, serviceType: "LoadBalancer",});nginx.url; // LB URL, e.g. "http://k8s-….elb.amazonaws.com"nginx.deploymentName; // K8s-native attrsAny cluster via kubeconfig
const local = Kubernetes.KubeConfig({ context: "kind-dev" });
const api = yield* Kubernetes.Deployment("Api", { cluster: local, image: "ghcr.io/acme/api:v3", port: 8080, serviceType: "ClusterIP",});Build your own Dockerfile
const legacy = yield* Kubernetes.Deployment("LegacyApp", { cluster, context: "./legacy", replicas: 2, port: 8080,});Effect Servers
Section titled “Effect Servers”Inline Effect server with a DynamoDB binding (EKS)
const api = yield* Kubernetes.Deployment( "Api", { cluster, main: import.meta.url, port: 3000, replicas: 2 }, Effect.gen(function* () { const putItem = yield* AWS.DynamoDB.PutItem(table); return { fetch: Effect.gen(function* () { yield* putItem({ Item: { id: { S: "1" } } }); return HttpServerResponse.text("ok"); }), }; }).pipe(Effect.provide(AWS.DynamoDB.PutItemHttp)),);Tagged Effect server
export class Api extends Kubernetes.Deployment<Api, { health: () => Effect.Effect<string>;}>()("Api") {}
export default Api.make( { cluster, main: import.meta.url, port: 3000 }, Effect.gen(function* () { return { fetch: Effect.gen(function* () { return HttpServerResponse.text("ok"); }), health: () => Effect.succeed("ok"), }; }),);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 deployment 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 },}Kubernetes Escape Hatch
Section titled “Kubernetes Escape Hatch”const tuned = yield* Kubernetes.Deployment("Api", { cluster, main: import.meta.url, port: 3000, podTemplate: { spec: { tolerations: [{ key: "gpu", operator: "Exists" }], nodeSelector: { pool: "arm" }, }, },});