Docs

Choose compute

Each piece of code in a stack, called a workload, runs as a Worker, a Container, or a Daemon. Each workload uses one of them, and one stack can mix all three.

alien.ts
// Event-driven function that scales to zero
const processor = new alien.Worker("processor")
  .code({ type: "source", src: "./processor", toolchain: { type: "typescript" } })
  .permissions("processor")
  .build()

// Long-running service with its own port
const ocr = new alien.Container("ocr")
  .code({ type: "image", image: "ghcr.io/acme/ocr:2.4.0" })
  .cpu(4)
  .memory("16Gi")
  .port(8080)
  .permissions("ocr")
  .build()

// One process on every machine in its pool
const collector = new alien.Daemon("collector")
  .code({
    type: "source",
    src: "./collector",
    toolchain: { type: "rust", binaryName: "collector" },
  })
  .permissions("collector")
  .build()
AWSGoogle CloudAzureKubernetes
WorkerLambdaCloud RunContainer AppsDeployment
ContainerEC2 machines Alien managesCompute Engine VMs Alien managesAzure VMs Alien managesPods
DaemonOne process per EC2 machineOne process per VMOne process per VMDaemonSet

Decision guide

You needUse
Code that reacts to uploads, queue messages, schedules, or commands, and scales to zeroWorker
A service that stays up: an API server, a database, a model server, anything with its own port or stateContainer
One agent per host: log or metrics collection, a sandbox runtime, anything that needs the host's filesystem or networkDaemon

Start with a Worker. Move to a Container when the work outlives a request, needs a GPU, or ships as an image you don't build with Alien. Use a Daemon only when the code must run on every machine.

To run code you don't trust, such as a customer's script or code a model wrote, use a Sandbox. Your app creates isolated sandboxes at runtime and runs commands inside them.

Worker

A Worker runs your handler on the cloud's serverless runtime. It starts on demand, so it costs nothing while idle.

alien.ts
const processor = new alien.Worker("processor")
  .code({ type: "source", src: "./processor", toolchain: { type: "typescript" } })
  .memoryMb(1024)
  .timeoutSeconds(120)
  .trigger({ type: "storage", storage: documents.ref(), events: ["created"] })
  .trigger({ type: "schedule", cron: "0 3 * * *" })
  .link(documents)
  .permissions("processor")
  .build()

This Worker indexes each new file in the documents bucket and runs a nightly job. Workers also receive commands and HTTP requests on a public endpoint. Defaults are 512 MB of memory and a 180 second timeout.

Tradeoffs:

  • On AWS, Workers build for linux-arm64 (Graviton) by default. A vendor image built only for x86 needs a Container instead.
  • Each invocation is bounded by the timeout. Long jobs belong in a Container, or split across queue messages.
  • Workers don't run on Machines (on-prem and bare-metal hosts). Use a Container or Daemon there.

Container

A Container is a long-running service with its own ports, replicas, and optional disk. Use it for an API server, a model server, or a database.

alien.ts
const ocr = new alien.Container("ocr")
  .code({ type: "image", image: "ghcr.io/acme/ocr:2.4.0" })
  .cpu(4)
  .memory("16Gi")
  .gpu({ type: "nvidia-t4", count: 1 })
  .minReplicas(1)
  .port(8080)
  .link(documents)
  .permissions("ocr")
  .build()

cpu and memory are required. Other options add autoscaling (.autoScale()), persistent volumes with backups (.persistentStorage()), health checks, and public HTTP or TCP endpoints. Code is a prebuilt image or a source folder with a docker, typescript, rust, or python toolchain.

Tradeoffs:

  • On AWS, Google Cloud, and Azure, Containers run on virtual machines in the customer's account. Machines cost money while they run, unlike an idle Worker.
  • GPUs (.gpu({ type, count })) work on cloud machines that offer them. Machines (on-prem hosts) don't support GPUs today.
  • On Machines, Containers must be stateless.

Private images

A Container can run an image from your private registry, such as GitHub Container Registry, Amazon ECR, or Docker Hub. Customers never need credentials for your registry:

  1. alien release runs docker pull --platform linux/<arch> for each target, with the Docker login of the machine that runs the release.
  2. The release copies the image into itself.
  3. Deployments pull it from your manager with their deployment token.

No registry credentials go into alien.ts, the templates, or the Helm values.

  • Log in on the machine or CI job that runs alien release. ECR login tokens expire after 12 hours, so log in in the same CI job.
  • The image must exist for every target architecture: linux/arm64 on AWS, linux/amd64 on Google Cloud and Azure, both on Kubernetes and Machines. Publish a multi-architecture image if you need more than one.
  • Pin the image by digest (ghcr.io/acme/api@sha256:...). Alien copies whatever the tag points to when the release runs.
  • If the pull fails, the release stops with docker pull failed for image '...' and Docker's output. Nothing is published.
  • alien release --registry-username and --registry-password set the registry the release is pushed to. They are not used to pull your image.

Only Containers get this copy. A Worker or Daemon with type: "image" keeps the reference as written, and the cloud must pull it without credentials. For a private base image, build the Worker or Daemon with the docker toolchain from a Dockerfile that starts FROM your image.

Daemon

A Daemon runs exactly one instance on each machine in its pool. Use it for host-level agents that read host files, watch the host network, or manage other processes on the host.

alien.ts
const collector = new alien.Daemon("collector")
  .code({
    type: "source",
    src: "./collector",
    toolchain: { type: "rust", binaryName: "collector" },
  })
  .runtime({ mounts: [{ source: "/var/log", target: "/host/var/log" }] })
  .link(documents)
  .permissions("collector")
  .build()

.runtime() grants host access: mounts, host network mode, the host PID namespace, or privileged mode. Grant only what the agent needs; the customer's security team will read it.

A Daemon scales with the number of machines, not with traffic.

Compute pools

Containers and Daemons run on a ComputeCluster: a set of machine pools in the customer's account. Alien creates a default cluster when a stack has Containers. Declare one yourself to define pools, for example a GPU pool that scales to zero next to a small fixed pool:

alien.ts
const compute = new alien.ComputeCluster("compute")
  .pool("gpu", {
    requirements: { cpu: 8, memory: "32Gi", accelerators: [{ type: "nvidia-t4", count: 1 }] },
    scale: { type: "autoscale", min: 0, max: 4 },
  })
  .pool("general", {
    requirements: { cpu: 2, memory: "8Gi", architecture: "arm64" },
    scale: { type: "fixed", machines: 2 },
  })
  .build()

Place a workload with .cluster("compute").pool("gpu"). Pools state portable requirements. The exact instance type is a deployment setting, so each customer can pick sizes during initial setup.

A ComputeCluster is always frozen: the customer's admin creates it during initial setup, and Alien manages the machines inside it afterwards. On Kubernetes, pools describe placement on the cluster's existing nodes and create no machines.

Where each type runs

AWS, Google Cloud, AzureKubernetesMachinesalien dev
WorkerYesYesNoNative process
ContainerYesYesStateless onlyDocker
DaemonYesYesYesNative process

The full matrix for every resource type is in Platforms. Every builder option is on the resource pages: Worker, Container, Daemon, ComputeCluster.

Next

On this page