Skip to content
GitHub Discord

MicroVm

The MicroVm component lets you run your code in AWS Lambda MicroVMs: isolated, stateful sandboxes, each with its own HTTPS endpoint, that live for up to 8 hours. For example, to run code that an AI agent wrote.

The component creates the image. Your app then starts MicroVMs from it, and sends them requests, with the SDK.

Create a MicroVM image

sst.config.ts
const sandbox = new sst.aws.MicroVm("Sandbox", {
image: { context: "./sandbox" },
dev: { command: "node app.js" }
});

Here ./sandbox has a Dockerfile that starts an app listening on port 8080.

sst.config.ts
new sst.aws.Function("MyFunction", {
handler: "src/lambda.handler",
link: [sandbox]
});
src/lambda.ts
import { Resource } from "sst";
import { microvm } from "sst/aws/microvm";
const vm = await microvm.run(Resource.Sandbox);
const res = await vm.fetch("/exec", {
method: "POST",
body: JSON.stringify({ code: "print(1 + 1)" })
});
await vm.terminate();

Reach private resources in a VPC

sst.config.ts
const vpc = new sst.aws.Vpc("MyVpc", { nat: "ec2" });
new sst.aws.MicroVm("Sandbox", {
image: { context: "./sandbox" },
vpc
});

Limit how long MicroVMs live

A MicroVM you don’t terminate keeps running until it’s idle, or until its duration is up. These defaults keep that short; change them for long sessions.

sst.config.ts
new sst.aws.MicroVm("Sandbox", {
image: { context: "./sandbox" },
duration: "4 hours",
idle: { suspendAfter: "10 minutes", terminateAfter: "1 hour" }
});

Your account has a quota for the memory of all its MicroVMs in a region, running and suspended, and each MicroVM has 2 GB. Once it’s reached, microvm.run() fails until some are terminated. You can ask for more in the Service Quotas console.


Constructor

new MicroVm(name, args?, opts?)

Parameters

MicroVmArgs

dev?

Type false | Object

Configure how this component works in sst dev.

By default, the image isn’t built in sst dev. Instead, dev.command runs your app on your machine, in a tab of the sst dev multiplexer, with the links and the execution role’s permissions.

In sst dev, the SDK sends the requests of every MicroVM you run to dev.url. So the MicroVMs aren’t isolated from each other the way they are once deployed.

So that the CLI can assume it, the execution role trusts your AWS account in sst dev, as Service’s and Task’s roles do. Any IAM user or role in the account whose policies allow sts:AssumeRole on it can then assume it too.

To build the image and run real MicroVMs in sst dev, pass in false.

dev.command?

Type Input<string>

The command that sst dev runs to start your app.

dev.directory?

Type Input<string>

Default The image.context

The directory the command runs in.

dev.url?

Type Input<string>

Default "http://localhost:8080", with your port

The URL your app listens on in sst dev.

duration?

Type Input<“${number} minute” | “${number} minutes” | “${number} hour” | “${number} hours” | “${number} second” | “${number} seconds”>

Default “1 hour”

The longest a MicroVM can exist, running and suspended. Lambda terminates it after this, up to 8 hours.

This is the default for microvm.run() in the SDK, which can override it.

environment?

Type Input<Record<string, Input<string>>>

Key-value pairs set as environment variables in the image.

They’re part of the image, so changing them rebuilds it. Lambda allows up to 50.

idle?

Type Input<false | Object>

Default { suspendAfter: “15 minutes”, terminateAfter: “15 minutes”, autoResume: true }

When a MicroVM gets no requests for a while, Lambda suspends it, and you stop paying for compute. Its memory and disk are kept. Then, if it stays suspended for too long, Lambda terminates it.

Pass false to keep MicroVMs running until duration is up.

This is the default for microvm.run() in the SDK, which can override it.

idle.autoResume?

Type Input<boolean>

Default true

Resume a suspended MicroVM when a request arrives for it.

idle.suspendAfter?

Type Input<“${number} minute” | “${number} minutes” | “${number} hour” | “${number} hours” | “${number} second” | “${number} seconds”>

Default “15 minutes”

How long a MicroVM can go without a request before it’s suspended. At least 1 minute.

idle.terminateAfter?

Type Input<“${number} minute” | “${number} minutes” | “${number} hour” | “${number} hours” | “${number} second” | “${number} seconds”>

Default “15 minutes”

How long a MicroVM can stay suspended before it’s terminated.

image?

Type Input<Object>

Default { context: ”.”, dockerfile: “Dockerfile” }

The image to run. Lambda builds it from your Dockerfile, on top of its Amazon Linux 2023 base image.

SST zips the context directory, puts the dockerfile at the root of the zip, and uploads it. Lambda builds the image from the zip, starts your app, and takes a snapshot that every MicroVM starts from. So your app starts once, at build time: anything it does on startup, like reading the time or generating an ID, is the same in every MicroVM.

A build takes a few minutes, and runs again whenever the code, the environment or a link’s values change. If it fails, the deploy fails, and the build’s logs are in the log group. MicroVMs keep starting from the last version that built.

Each build adds a version to the image, and Lambda allows 50. After a build, SST deletes the old ones. It keeps the newest 5 that built, and any that MicroVMs still run from.

Lambda runs the Dockerfile itself, so Docker build args, targets, secrets and caches don’t apply. Files matched by a .dockerignore in the context aren’t uploaded, and neither are the sst-env.d.ts files SST generates, so writing them doesn’t rebuild the image.

{
image: {
context: "./sandbox",
dockerfile: "Dockerfile"
}
}

image.context?

Type Input<string>

Default ”.”

The path to the directory that’s zipped and uploaded, relative to your project root.

image.dockerfile?

Type Input<string>

Default “Dockerfile”

The path to the Dockerfile, relative to the context.

Type Input<any[]>

Link resources to your MicroVMs. This grants the execution role the permissions of the linked resources, and sets them as environment variables in the image, so your app can read them through the SDK.

Changing a linked resource’s values rebuilds the image.

To read them with Resource, add sst to your app’s dependencies. It comes with the SST CLI, about 75 MB, as an optional dependency that your app doesn’t need. To leave it out of the image, install with npm install --omit=optional.

{
link: [bucket]
}

logging?

Type Input<Object>

Default { retention: “1 month” }

Configure the log group for your MicroVMs’ logs.

logging.retention?

Type Input<“1 day” | “3 days” | “5 days” | “1 week” | “2 weeks” | “1 month” | “2 months” | “3 months” | “4 months” | “5 months” | “6 months” | “1 year” | “13 months” | “18 months” | “2 years” | “3 years” | “5 years” | “6 years” | “7 years” | “8 years” | “9 years” | “10 years” | “forever”>

Default “1 month”

How long to keep the logs.

permissions?

Type Input<Object[]>

Permissions and the resources that your MicroVMs need to access. They’re added to the execution role.

{
permissions: [
{
actions: ["bedrock:InvokeModel"],
resources: ["*"]
}
]
}

permissions[].actions

Type string[]

The IAM actions that can be performed.

{
actions: ["s3:*"]
}

permissions[].conditions?

Type Input<Input<Object>[]>

Configure specific conditions for when the policy is in effect.

{
conditions: [
{
test: "StringEquals",
variable: "s3:x-amz-server-side-encryption",
values: ["AES256"]
},
{
test: "IpAddress",
variable: "aws:SourceIp",
values: ["10.0.0.0/16"]
}
]
}
permissions[].conditions[].test

Type Input<string>

Name of the IAM condition operator to evaluate.

permissions[].conditions[].values

Type Input<Input<string>[]>

The values to evaluate the condition against. If multiple values are provided, the condition matches if at least one of them applies. That is, AWS evaluates multiple values as though using an “OR” boolean operation.

permissions[].conditions[].variable

Type Input<string>

Name of a Context Variable to apply the condition to. Context variables may either be standard AWS variables starting with aws: or service-specific variables prefixed with the service name.

permissions[].effect?

Type “allow” | “deny”

Default “allow”

Configures whether the permission is allowed or denied.

{
effect: "deny"
}

permissions[].resources

Type Input<Input<string>[]>

The resourcess specified using the IAM ARN format.

{
resources: ["arn:aws:s3:::my-bucket/*"]
}

port?

Type Input<number>

Default 8080

The port your app listens on. The SDK sends requests to this port.

transform?

Type Object

Transform how this component creates its underlying resources.

transform.buildRole?

Type RoleArgs | (args: RoleArgs, opts: ComponentResourceOptions, name: string) => void

Transform the IAM role Lambda uses to build the image.

transform.executionRole?

Type RoleArgs | (args: RoleArgs, opts: ComponentResourceOptions, name: string) => void

Transform the IAM role your MicroVMs run with.

transform.image?

Type ImageArgs | (args: ImageArgs, opts: ComponentResourceOptions, name: string) => void

Transform the MicroVM image resource.

transform.logGroup?

Type LogGroupArgs | (args: LogGroupArgs, opts: ComponentResourceOptions, name: string) => void

Transform the CloudWatch log group.

transform.networkConnector?

Type CoreNetworkConnectorArgs | (args: CoreNetworkConnectorArgs, opts: ComponentResourceOptions, name: string) => void

Transform the Lambda network connector, created when vpc is set.

transform.operatorRole?

Type RoleArgs | (args: RoleArgs, opts: ComponentResourceOptions, name: string) => void

Transform the IAM role Lambda uses to create the network connector’s network interfaces in the VPC.

vpc?

Type Vpc | Input<Object>

Send your MicroVMs’ outbound traffic through the private subnets of a VPC, so they can reach private resources, like a database.

Requests to a MicroVM still come in through its HTTPS endpoint. Only its outbound traffic goes through the VPC, and it reaches the internet only through the VPC’s NAT.

This creates a Lambda network connector that every MicroVM is run with. Creating it takes about 5 minutes. Lambda’s docs say to terminate the MicroVMs that use it before it’s changed or removed.

Create a Vpc component, with a NAT if your MicroVMs need the internet.

sst.config.ts
const myVpc = new sst.aws.Vpc("MyVpc", { nat: "ec2" });

And pass it in.

{
vpc: myVpc
}

Or pass in the subnets and security groups of an existing VPC.

{
vpc: {
privateSubnets: ["subnet-0b6a2b73896dc8c4c", "subnet-021389ebee680c2f0"],
securityGroups: ["sg-0399348378a4c256c"]
}
}

vpc.privateSubnets

Type Input<Input<string>[]>

A list of VPC subnet IDs.

vpc.securityGroups

Type Input<Input<string>[]>

A list of VPC security group IDs.

Properties

arn

Type undefined | Output<string>

The ARN of the MicroVM image. Not created in sst dev, unless dev is false.

nodes

Type Object

The underlying resources this component creates.

nodes.buildRole

Type undefined | Role

The IAM role Lambda uses to build the image.

nodes.executionRole

Type Role

The IAM role your MicroVMs run with.

nodes.image

Type undefined | Image

The MicroVM image. Not created in sst dev, unless dev is false.

nodes.logGroup

Type LogGroup

The CloudWatch log group.

nodes.networkConnector

Type undefined | CoreNetworkConnector

The Lambda network connector. Only created when vpc is set, and not in sst dev.

SDK

Use the SDK in your runtime to interact with your infrastructure.


The microvm client SDK is available through the following.

src/app.ts
import { microvm } from "sst/aws/microvm";

If you are not using Node.js, you can use the AWS SDK instead, with the link data in Resource. For example, call RunMicrovm with its imageArn, imageVersion and executionRoleArn.


get

microvm.get(resource, id, options?)

Parameters

Returns Promise<MicroVm>

Gets a MicroVM that’s already running, by its ID. Use this to reach the same MicroVM from a later request.

src/app.ts
const vm = await microvm.get(Resource.Sandbox, id);
const res = await vm.fetch("/status");

run

microvm.run(resource, options?)

Parameters

Returns Promise<MicroVm>

Runs a new MicroVM from the image, and waits until it’s running.

For example, let’s say you have a MicroVM image.

sst.config.ts
new sst.aws.MicroVm("Sandbox", { image: { context: "./sandbox" } });

Run a MicroVM from it, send it requests, and terminate it.

src/app.ts
import { Resource } from "sst";
import { microvm } from "sst/aws/microvm";
const vm = await microvm.run(Resource.Sandbox);
const res = await vm.fetch("/hello");
await vm.terminate();

In sst dev, this doesn’t start a MicroVM. The requests go to your app running on your machine, and terminate does nothing.

DescribeResponse

DescribeResponse.id

Type string

The ID of the MicroVM.

DescribeResponse.response

Type any

The raw response from the AWS API.

DescribeResponse.state

Type State

The state of the MicroVM. AWS updates it eventually, so it can lag behind.

DescribeResponse.stateReason?

Type string

Why the MicroVM is in this state.

DescribeResponse.url

Type string

The URL of the MicroVM.

FetchInit

Type Object

FetchInit.port?

Type number

The port to send the request to, if not the component’s port.

MicroVm

MicroVm.id

Type string

The ID of the MicroVM. Keep it to reach the same MicroVM later, with get.

MicroVm.url

Type string

The URL of the MicroVM. A request to it needs a token from token, in the X-aws-proxy-auth header. fetch adds it for you.

MicroVm.describe

describe()

Returns Promise<DescribeResponse>

Gets the MicroVM’s state.

MicroVm.fetch

fetch(path, init?)

Parameters

Returns Promise<Response<>>

Sends a request to the app in the MicroVM. It works like fetch, with a path instead of a URL, and adds the token.

const res = await vm.fetch("/exec", {
method: "POST",
body: JSON.stringify({ code })
});

MicroVm.resume

resume()

Returns Promise<void>

Resumes a suspended MicroVM.

MicroVm.suspend

suspend()

Returns Promise<void>

Suspends the MicroVM. Its memory and disk are kept, and you stop paying for compute.

MicroVm.terminate

terminate()

Returns Promise<void>

Terminates the MicroVM.

MicroVm.token

token(port?)

Parameters

  • port? number

Returns Promise<string>

A token for requests to a port of the MicroVM, valid for up to an hour. fetch refreshes it before it expires. Use this to let something else, like a browser, reach the MicroVM.

Options

Type Object

Options.aws?

Type Object

Configure the options for the aws4fetch AWSClient used internally by the SDK.

Resource

Resource.dev?

Type Object

Set in sst dev, where the app runs on your machine.

Resource.dev.url

Type string

Resource.duration?

Type number

The longest a MicroVM can exist, in seconds.

Resource.egressNetworkConnectors?

Type string[]

The network connectors a MicroVM reaches the internet through.

Resource.executionRoleArn?

Type string

The ARN of the role MicroVMs run with.

Resource.idle?

Type IdlePolicy

When an idle MicroVM is suspended, and then terminated.

Resource.imageArn?

Type string

The ARN of the MicroVM image.

Resource.imageVersion?

Type string

The version of the image that was deployed.

Resource.ingressNetworkConnectors?

Type string[]

The network connectors that let requests reach a MicroVM.

Resource.logGroup?

Type string

The log group the MicroVMs’ logs go to.

Resource.port

Type number

The port the app in a MicroVM listens on.

RunOptions

RunOptions.aws?

Type Object

Configure the options for the aws4fetch AWSClient used internally by the SDK.

RunOptions.duration?

Type “${number} second” | “${number} seconds” | “${number} minute” | “${number} minutes” | “${number} hour” | “${number} hours”

Overrides the component’s duration: the longest this MicroVM can exist, running and suspended. Up to 8 hours.

RunOptions.idle?

Type false | Object

Overrides the component’s idle. Pass false to keep this MicroVM running until its duration is up.

RunOptions.idle.autoResume?

Type boolean

RunOptions.idle.suspendAfter?

Type “${number} second” | “${number} seconds” | “${number} minute” | “${number} minutes” | “${number} hour” | “${number} hours”

RunOptions.idle.terminateAfter?

Type “${number} second” | “${number} seconds” | “${number} minute” | “${number} minutes” | “${number} hour” | “${number} hours”

RunOptions.timeout?

Type “${number} second” | “${number} seconds” | “${number} minute” | “${number} minutes” | “${number} hour” | “${number} hours”

Default “1 minute”

How long run waits for the MicroVM to be running.