Freestyle VMs are designed as durable runtime objects. Your application can start work, pause it when idle, start it again later, and delete it when no longer needed. These capabilities enable powerful workflows for task execution and rapid iteration.
Running
The VM is executing and can accept commands, SSH sessions, and network traffic.
const { vm } = await freestyle.vms.create({
// Required: a VM reaches nothing it has not been allowed to.
firewall: { rules: [{ action: "allow", source: {}, destination: { public: true } }] },
});
await vm.exec("echo running");
Paused
Pausing freezes the VM and saves its memory. Starting it again resumes the same processes at the same point, with open files and in-memory state intact. Use pause() when you want to come back to exactly this VM.
await vm.pause();
await vm.start();
A paused VM does not count against your concurrent VM limit. It still holds its disk and its saved memory, so it does count as a saved VM.
Your files stay accessible while compute stays paused. Read files, browse directories, or download artifacts through vm.fs without resuming the VM. File writes and other filesystem changes wake it automatically. See Read Files While Paused.
Stopped
Prefer pause() when you plan to use a VM again. Pausing preserves its running
processes and memory, so start() can resume where it left off.
Stop a VM only when you need a fresh boot. A stopped VM keeps its disk but
discards its memory. Power it off from inside the guest, then wait until it
reports stopped before starting it again:
await vm.exec("poweroff").catch(() => {});
while ((await freestyle.vms.get(vmId)).state !== "stopped") {
await new Promise((resolve) => setTimeout(resolve, 500));
}
await vm.start();
The poweroff command rejects because the VM shuts down before it can return
an exit status. Catching that disconnect is expected.
Only persistent VMs can be started again. Ephemeral VMs are deleted when they stop.
Resize
Use resize() to size a VM for your workload after it exists. Pass any of cpu, memory, and storage to change the VM’s CPU, memory, or root filesystem size.
await vm.resize({
cpu: 8,
memory: 16 * 1024,
storage: 80 * 1024,
});
Resizing is up-only: none of cpu, memory, or storage can be reduced. To move to a smaller shape, create a new VM.
Resizing happens live. On a running VM the new CPU and memory come online without a reboot, and the disk grows in place while the guest keeps running. On a paused VM the new CPU and memory apply when it resumes. On a stopped VM they apply at its next start. Growing the disk needs a running VM, so start it first. Memory and storage are measured in MiB; requested sizes are subject to your account limits.
Idle Timeout
Configure an idle timeout to let Freestyle pause VMs that have no network activity.
Set it when you create the VM, or change it later:
await vm.update({ idleTimeoutSeconds: 600 });
A VM paused this way resumes on its next start, or on the next traffic that reaches it. Set idleTimeoutSeconds to -1 with vm.update() to remove the configured timeout.
For a domain protected by forward auth, authorization runs before wake-up. A denied request or an unavailable authorizer leaves the VM paused.
Deadlines And Runtime Limits
Choose the policy that matches the workspace’s lifetime. These fields can
be set at creation or changed with vm.update():
| Field | Behavior |
|---|---|
ttlSeconds | Delete after this many seconds from createdAt, including time spent paused or stopped |
maxRunSeconds | Pause after this many seconds in one run; starting again gives a fresh budget |
maxRunTotalSeconds | Pause after this many running seconds across all runs; raise the budget before starting again |
autoDeleteSeconds | Delete after this many seconds continuously paused or stopped; 0 makes the VM ephemeral |
To set or extend a deletion deadline, convert the desired time to seconds from creation, not seconds from now:
const { createdAt } = await vm.data();
const deadline = Date.now() + 30 * 60 * 1000; // thirty minutes from now
await vm.update({
ttlSeconds: Math.ceil((deadline - Date.parse(createdAt)) / 1000),
});
Deletion is asynchronous: expired VMs are collected by a periodic sweep,
so ttlSeconds is not an exact-time scheduler. To pause at an application
lease deadline, have your backend call vm.pause() when that lease expires.
Set a field to -1 to remove it. Some plans cap autoDeleteSeconds; on
those plans, -1 restores the plan’s cap. Read vm.data() for the effective
policy.
Delete
Delete VMs when the workspace is finished.
await freestyle.vms.delete(vmId);
Deleting is permanent for the VM. Snapshot or copy out any state you need before deleting it.