Skip to content

Commit 82a66a5

Browse files
committed
lifetimes
1 parent 0936993 commit 82a66a5

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

sandboxes/_data.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export const sidebar = [
2626
title: "Volumes",
2727
href: "/sandboxes/reference/volumes/",
2828
},
29+
{
30+
title: "Lifetimes",
31+
href: "/sandboxes/reference/lifetimes/",
32+
},
2933
{
3034
title: "API Reference",
3135
href: "https://jsr.io/@deno/sandbox/doc/~/Sandbox",

sandboxes/reference/lifetimes.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
title: "Sandbox Lifetimes"
3+
description: "Understand how long sandboxes stay alive, how to extend or reconnect to them, and when to promote work to a Deploy app."
4+
---
5+
6+
Sandboxes are intentionally ephemeral. They boot in milliseconds, serve their
7+
purpose, and disappear—reducing the blast radius of untrusted code and removing
8+
infrastructure chores. Still, you can control exactly how long a sandbox stays
9+
alive and even reconnect later when debugging is required.
10+
11+
## Default lifetime: `"session"`
12+
13+
```tsx
14+
await using sandbox = await Sandbox.create();
15+
```
16+
17+
With no options set, the sandbox lives for the duration of your script. Once the
18+
`Sandbox` instance is closed, the microVM shuts down and frees all resources.
19+
This keeps costs predictable and prevents orphaned infrastructure.
20+
21+
## Duration-based lifetimes
22+
23+
Provide a duration string to keep a sandbox alive after the client disconnects:
24+
25+
```tsx
26+
const sandbox = await Sandbox.create({ lifetime: "5m" });
27+
const id = sandbox.id;
28+
await sandbox.close(); // process can exit now
29+
30+
// later
31+
const reconnected = await Sandbox.connect({ id });
32+
```
33+
34+
Supported suffixes: `s` (seconds) and `m` (minutes). Examples: `"30s"`, `"5m"`,
35+
`"90s"`. Use this mode for manual inspection, SSH debugging, or when a bot needs
36+
to resume work mid-way.
37+
38+
## Forcefully ending a sandbox
39+
40+
- `await sandbox.kill()` immediately stops the VM and releases the lifetime.
41+
- Killing a sandbox invalidates exposed HTTP URLs, SSH sessions, and any
42+
attached volumes.
43+
44+
## Ephemeral compute vs Deploy apps
45+
46+
| Aspect | Sandboxes | Deploy Apps |
47+
| ------------- | ---------------------------------------- | -------------------------------------- |
48+
| Lifetime | Seconds to minutes | Always-on, managed rollouts |
49+
| Control plane | Programmatic via SDK | Dashboard + CI/CD |
50+
| Use cases | Agents, previews, untrusted code | Production APIs, long-lived services |
51+
| State | Ephemeral (use volumes when needed) | Durable deployments with KV, databases |
52+
| Exposure | `exposeHttp()`/`exposeSsh()` per sandbox | Custom domains, TLS, routing built-in |
53+
54+
Start in a sandbox to iterate quickly. Once the codebase stabilizes and needs
55+
24/7 availability, promote it to a Deploy app where builds, rollouts, and
56+
observability are managed for you.
57+
58+
## Promote with `sandbox.deploy()`
59+
60+
When a sandbox proves the concept, you can turn it into an always-on Deploy app
61+
without rebuilding elsewhere. `sandbox.deploy()` snapshots the current file
62+
system, carries over `allowNet`, and provisions an app with a durable URL,
63+
observability, and team access.
64+
65+
```tsx
66+
await using sandbox = await Sandbox.create({ lifetime: "10m" });
67+
// ...build or scaffold your service...
68+
69+
const app = await sandbox.deploy({
70+
name: "ai-preview",
71+
entrypoint: "server.ts",
72+
});
73+
console.log(`Promoted to Deploy app ${app.slug}`);
74+
```
75+
76+
Reasons to promote:
77+
78+
- Keep a sandbox experiment running for customer traffic with production SLAs.
79+
- Get TLS, custom domains, rollbacks, and traffic splitting handled for you.
80+
- Share observability (logs/traces/metrics) across the team via the Deploy UI.
81+
- Replace brittle hand-offs; the exact sandbox state becomes the deployed
82+
revision.
83+
84+
Use sandboxes for rapid, ephemeral work, then call `sandbox.deploy()` when the
85+
code should live as a managed service.
86+
87+
## Lifetime best practices
88+
89+
- Keep lifetimes short for untrusted or user-supplied code. Smaller windows
90+
reduce attack surface.
91+
- Use metadata (e.g., `metadata: { owner: "agent-42" }`) to track who owns a
92+
sandbox that outlives its creator.
93+
- Pair longer lifetimes with explicit `allowNet` rules and rate limits if
94+
running internet-facing workloads.
95+
- Clean up proactively: scripts should call `kill()` once the workload ends,
96+
rather than waiting for the duration to expire.
97+
98+
## Related APIs
99+
100+
- [`Sandbox.create()`](./create.md) – pass the `lifetime` option when
101+
provisioning.
102+
- `Sandbox.connect({ id })` – resume control of a duration-based sandbox.
103+
- `Sandbox.kill()` – terminate early.
104+
- [`Expose HTTP`](./expose_http.md) and [`Expose SSH`](./expose_ssh.md) – note
105+
that their URLs/credentials die with the sandbox lifetime.

0 commit comments

Comments
 (0)