How Alien Works
Alien provides infrastructure for deploying managed software into your customer's cloud. You define your application once, Alien handles provisioning, updates, and monitoring across every customer environment.
Let's walk through how it works, step by step.
One codebase, any cloud
You'll have customers on AWS, GCP, and Azure. Do you need to build separate integrations for each one?
No. With Alien, you define the infrastructure your application needs once, in a file called alien.ts:
import * as alien from "@alienplatform/core"
const data = new alien.Storage("data").build()
const secrets = new alien.Vault("credentials").build()
const api = new alien.Worker("api")
.code({ type: "source", src: "./api", toolchain: { type: "typescript" } })
.link(data)
.link(secrets)
.publicEndpoint("api")
.permissions("execution")
.build()
export default new alien.Stack("my-app")
.add(api, "live")
.add(data, "frozen")
.add(secrets, "frozen")
.build()Alien translates each resource to the native service at deploy time:
┏━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━┓
┃ Worker ┃ ┃ Storage ┃
┗━━━━━┯━━━━━━┛ ┗━━━━━┯━━━━━━┛
│ │
├── AWS ───▶ Lambda ├── AWS ───▶ S3
├── GCP ───▶ Cloud Run ├── GCP ───▶ Google Cloud Storage
└── Azure ─▶ Container App └── Azure ─▶ Azure Blob StorageThe same applies to queues, vaults, KV stores, and networking. See Stacks for the full reference.
Notice .add(api, "live") and .add(data, "frozen"). The lifecycle says who owns changes after setup:
- Frozen: customer setup owns it. A normal rollout cannot create, change, replace, or delete it.
- Live: Alien's Deployment Manager can create, update, replace, or remove it during a rollout.
Learn more about frozen and live resources.
Your code
Because your code runs inside the customer's network, it can reach things that aren't accessible from the outside: internal wikis, private databases, on-prem APIs.
Here's an example: an API that crawls the customer's internal Confluence and caches pages in their cloud storage. An AI agent in your cloud calls this to build a knowledge base from internal docs.
import { Hono } from "hono"
import { storage } from "@alienplatform/sdk"
import { chromium } from "playwright"
const app = new Hono()
const pages = storage("pages") // S3 / Cloud Storage / Blob Storage
// Crawl a page from the customer's internal wiki.
// This URL is only reachable from inside their network.
app.post("/crawl", async (c) => {
const { url } = await c.req.json()
const browser = await chromium.launch()
const page = await browser.newPage()
await page.goto(url) // e.g. https://wiki.corp.internal/page/123
const data = {
title: await page.textContent("h1"),
body: await page.textContent("#main-content"),
}
await browser.close()
// Cache in the customer's own storage
await pages.put(`${encodeURIComponent(url)}.json`, Buffer.from(JSON.stringify(data)))
return c.json(data)
})
// Retrieve a previously crawled page
app.get("/pages/:key", async (c) => {
const object = await pages.get(c.req.param("key"))
return c.json(JSON.parse(object.data.toString("utf8")))
})
// Export the HTTP app — Alien's worker runtime serves it, no serve() call needed
export default appYou can also use the native cloud SDKs directly (e.g. @aws-sdk/client-s3) if you prefer. Alien injects the credentials and connection details either way. See Accessing Resources.
Build and test locally with alien dev. Alien provides local equivalents for every resource: storage on the filesystem, vaults in an embedded store, queues in memory. Same API, no cloud credentials needed. See Local Development.
The isolated area
Now that we know what we're deploying, where does it actually go inside the customer's cloud?
Their cloud account contains their own databases, services, networking, and storage. They don't want you anywhere near that.
So your application gets its own isolated area within their account. Your resources live inside it. Everything outside is off-limits.
╔═ Customer's Cloud Account ═════════════════════════════════╗
║ ║░
║ Their databases, services, networking, storage ║░
║ ║░
║ ┌─ Isolated Area (your application) ────────────────┐ ║░
║ │ │ ║░
║ │ ┏━━━━━━━━━━┓ ┏━━━━━━━━━━┓ ┏━━━━━━━━━━┓ │ ║░
║ │ ┃ Worker ┃ ┃ Storage ┃ ┃ Queue ┃ │ ║░
║ │ ┗━━━━━━━━━━┛ ┗━━━━━━━━━━┛ ┗━━━━━━━━━━┛ │ ║░
║ │ │ ║░
║ └───────────────────────────────────────────────────┘ ║░
║ ║░
╚════════════════════════════════════════════════════════════╝░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░What does "isolated area" mean concretely? It depends on the cloud:
- Azure: a resource group
- GCP: a dedicated project
- AWS: a set of resources that share a naming prefix (e.g.
acme-*)
See Cloud Scoping for details on each provider.
Your application can also connect to the customer's existing resources (a database, an internal API, a secret store) if they choose to allow it.
Ongoing management
Now that we know what we're deploying and where it goes: how do you manage it?
With traditional self-hosting, you hand the customer a Docker image or Helm chart. They run it themselves. Your code is in their cloud, but:
- Every customer runs a different version
- You have no logs, no metrics, no visibility
- When something breaks, you schedule a call or wait days for a partial log dump
- You can't push a fix without asking them to re-deploy manually
With Alien, the customer shares access to the isolated area with your account. Think of sharing a Google Drive folder: they share a specific folder, you can manage what's inside, they can revoke access at any time.
Not every customer will agree to share cross-account access. For those cases, there's an Operator alternative that doesn't require it.
Within the shared area, what you can do is limited:
- Can: update application code, monitor health, collect telemetry (sent outbound via OpenTelemetry)
- Cannot: create or delete infrastructure, read customer data, access anything outside the area
Alien automatically derives least-privilege permissions from your stack definition. The customer's security team only needs to review what's actually required.
The Alien Deployment Manager
The Alien Deployment Manager runs in your own cloud. It's the control plane that manages all customer deployments from one place — alien.dev provisions and operates it for you, or you can self-host.
╔═ Your Cloud ══════════════════════╗ ╔═ Customer's Cloud ══════════════════╗
║ ║ ║ ║░
║ ┌── Alien Deployment Manager ──┐ ║ ║ Their databases, services, infra ║░
║ │ │ ║ ║ ║░
║ │ │ ║ ║ ┌─ Isolated Area ──────────────┐ ║░
║ │ │ ║ cloud APIs ║ │ │ ║░
║ │ Push updates ─────────┼─╬────────────────╬─▶│ ┏━━━━━━━━━━┓ │ ║░
║ │ Collect telemetry ◀────────┼─╬────────────────╬──│ ┃ Worker ┃ │ ║░
║ │ Worker commands ─────────┼─╬────────────────╬─▶│ ┗━━━━━━━━━━┛ │ ║░
║ │ │ ║ ║ │ ┏━━━━━━━━━━┓ │ ║░
║ │ │ ║ ║ │ ┃ Storage ┃ │ ║░
║ └──────────────────────────────┘ ║ ║ │ ┗━━━━━━━━━━┛ │ ║░
║ ║ ║ │ │ ║░
╚═══════════════════════════════════╝ ║ └──────────────────────────────┘ ║░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║ ║░
╚═════════════════════════════════════╝░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░The Deployment Manager manages resources by calling cloud provider APIs (e.g. UpdateFunctionCode on AWS). No network connection to the customer's environment is needed.
How access works
Every cloud provider has a built-in mechanism for granting scoped access:
- Azure: managed identity
- GCP: service account impersonation
- AWS: cross-account IAM role
No passwords or keys are exchanged. The cloud provider handles the trust.
See Impersonation for details.
This is the push model. It's the default for AWS, GCP, and Azure.
The Operator alternative
Some security teams won't allow cross-account access at all. They don't want any external identity in their cloud, even a scoped one.
For those environments, a lightweight Operator runs inside the customer's isolated area. It connects outbound to the Alien Deployment Manager, fetches releases, and deploys them locally.
╔═ Your Cloud ══════════════════════╗ ╔═ Customer's Cloud ══════════════════╗
║ ║ ║ ║░
║ ┌── Alien Deployment Manager ──┐ ║ ║ Their databases, services, infra ║░
║ │ │ ║ ║ ║░
║ │ │ ║ HTTPS ║ ┌─ Isolated Area ──────────────┐ ║░
║ │ │ ║ (outbound) ║ │ │ ║░
║ │ Fetch releases ◀───────────┼─╬────────────────╬──│─── ┏━━━━━━━━━┓ │ ║░
║ │ Send telemetry ◀───────────┼─╬────────────────╬──│─── ┃Operator ┃ │ ║░
║ │ Fetch Worker work ◀─────────┼─╬────────────────╬──│─── ┗━━━━┯━━━━┛ │ ║░
║ │ │ ║ ║ │ │ push │ ║░
║ │ │ ║ ║ │ ┏━━━━▼━━━━━┓ │ ║░
║ │ │ ║ ║ │ ┃ Worker ┃ │ ║░
║ └──────────────────────────────┘ ║ ║ │ ┗━━━━━━━━━━┛ │ ║░
║ ║ ║ │ ┏━━━━━━━━━━┓ │ ║░
╚═══════════════════════════════════╝ ║ │ ┃ Storage ┃ │ ║░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ║ │ ┗━━━━━━━━━━┛ │ ║░
║ └──────────────────────────────┘ ║░
No cross-account access. ║ ║░
No inbound ports. ╚═════════════════════════════════════╝░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░The Deployment Manager never touches the customer's cloud directly. The Operator deploys using its own local credentials.
The Operator polls for deployment state and releases. It also leases pending
Worker commands and pushes them to the targeted Worker runtime inside the
customer's environment, so the Worker never polls the command server. A
Container or Daemon runs its own receiver from @alienplatform/commands (or
alien-commands in Rust); the Operator does not run that receiver or its
handlers. Each app-owned receiver can lease only its own targeted work.
This is the pull model, used for on-prem or stricter security teams.
Both models give you the same capabilities. Use push when possible. See Deployment Models.
When Alien didn't deploy it
Some teams already ship BYOC with Terraform, Pulumi, Helm, or raw manifests. For those environments, Alien can run in Operate mode instead of Build mode.
Operate creates an observe-only deployment. The customer installs the Operator or grants read-only cloud inventory access, and Alien reports existing resources, health, and connectivity without reconciling a stack or changing workloads.
See Operate Existing Environments.
Initial setup
Before the Deployment Manager can deploy the application, the customer completes setup once.
You generate a deployment link for the customer and they open it in a browser. The link leads to a white-labeled deployment portal — branded for your project — with four ways to do the initial setup:
- a CLI auto-generated and branded for your project (e.g.
acme-deploy) - a Terraform module to drop into an existing workspace
- a CloudFormation template for one-click launch on AWS
- a Helm chart for installing into an existing Kubernetes cluster
The admin picks whichever fits their workflow and runs it with their own cloud credentials. Whichever method they choose prepares the same deployment:
- Frozen infrastructure owned by setup
- The service identity that the Deployment Manager will use for ongoing management
- The configuration needed to provision live resources
The admin needs elevated permissions because they're creating resources that don't exist yet.
After setup, the Deployment Manager uses its auto-derived permissions to create and reconcile live resources. Frozen resources remain owned by setup; changing them requires the customer to run setup again. Health checks and telemetry are separate features with their own permissions.
Releases
alien releaseEvery active deployment picks up the new version:
- Push mode: the Deployment Manager reconciles live resources immediately
- Pull mode: the Operator picks it up on its next poll (~30 seconds)
One command. Every customer updated. No coordination.
After deployment
Once deployed, you have full visibility and control through the Deployment Manager.
Telemetry
Logs, metrics, and traces flow back from every customer environment. Debug issues without asking the customer to send you anything.
Remote commands
Invoke code inside the customer's VPC. The command travels through the Deployment Manager. No inbound ports, no VPN:
import { command, vault } from "@alienplatform/sdk"
import { Pool, type PoolConfig } from "pg"
// Runs inside the customer's environment
command("get-user-count", async () => {
const config = await vault("credentials").getJson<PoolConfig>("database")
const pool = new Pool(config)
const { rows } = await pool.query("SELECT count(*) FROM users")
return rows[0]
})Your control plane targets the resource that registered the handler:
import { CommandsClient } from "@alienplatform/commands"
const commands = new CommandsClient({ managerUrl, deploymentId, token })
const result = await commands.target("customer-tools").invoke("get-user-count", {})alien commands invoke \
--deployment acme-corp \
--command get-user-count \
--params '{}'This is how AI agents execute tool calls, data connectors run queries, and security scanners report results. Workers always receive pushes from the Manager or in-environment Operator; app-owned Container and Daemon receivers lease their own targeted commands over outbound HTTPS.
See Remote Commands.
Events
React to things happening inside the customer's environment:
onQueueMessage("tasks", async (msg) => {
// A message arrived in the customer's queue
})
onStorageEvent("uploads", async (event) => {
// A file was uploaded to the customer's bucket
})
onCronEvent("nightly", async () => {
// Runs on schedule
})See Events & Triggers.