# Sandbox persistence
<subtitle>Pauses the sandbox and later restores it to the same state, preserving the file system and in-memory runtime context. </subtitle>

Sandbox persistence allows you to pause a running sandbox and later restore it to the state it was in when it was paused.

This includes not only the files in the sandbox file system, but also the memory state: running processes, loaded variables, cached data, etc. are all saved.

> Paused sandboxes and sandbox snapshots will occupy persistent storage and be billed according to persistent storage rules. For detailed billing methods, please refer to [Billing Instructions](/docs/agent-sandbox/product/fee.md).

## Status flow

Understanding how the sandbox switches between different states can help you manage the lifecycle more precisely. The following figure shows common status flows:

```mermaid actions={false}
flowchart TD
    start(( )) -->|Sandbox.create| A

    A["<b>Running</b><br/>• Executing tasks<br/>• Consuming computing resources"]
    B["<b>Paused</b><br/>• Reserve memory and files<br/>• Cannot execute code"]
    C["<b>Snapshotting</b><br/>• Create a persistent snapshot<br/>• Briefly pause execution"]
    D["<b>Killed</b><br/>• Resource has been released<br/>• Cannot be restored"]

    A -->|pause| B
    A -->|createSnapshot| C
    B -->|connect| A
    C -->|Snapshot completed|A
    A -->|kill| D
    B -->|kill| D
```

### Status description

- **Running**: The sandbox is running and code can be executed. This is the initial state after creation.
- **Paused**: Sandbox execution is suspended, but state will be retained.
- **Snapshotting**: The sandbox is creating persistent snapshots. The sandbox will be paused briefly during the creation process, and will automatically return to the Running state after completion.
- **Killed**: The sandbox has been terminated and resources have been released. This is the final state and cannot be restored.

### Switch sandbox status

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create() # Enter the running state after creation
sandbox_id = sandbox.sandbox_id

# Pause the sandbox: running -> paused
sandbox.pause()

#Restore sandbox: paused -> running
same_sandbox = Sandbox.connect(sandbox_id)

# Destroy sandbox: running/paused -> destroyed
same_sandbox.kill()
```

## Pause sandbox

After calling `pause()`, the file system and memory state of the sandbox will be saved. You can save the sandbox ID to a database or business state and use it to restore the same sandbox later.

```python
from ucloud_sandbox import Sandbox

sbx = Sandbox.create()
print("Sandbox has been created", sbx.sandbox_id)

# Pause the sandbox and save sbx.sandbox_id for later resumption
sbx.pause()
print("Sandbox has been paused", sbx.sandbox_id)
```

## Restore sandbox

When you resume the sandbox, it returns to the state it was in when it was paused. The file system is restored, and running processes, loaded variables, and memory data are restored.

```python
from ucloud_sandbox import Sandbox

sbx = Sandbox.create()
print("Sandbox has been created", sbx.sandbox_id)

# Pause the sandbox and save the ID
sandbox_id = sbx.sandbox_id
sbx.pause()
print("Sandbox has been paused", sandbox_id)

# Connect to the sandbox; if the target is paused, it will automatically resume
same_sbx = Sandbox.connect(sandbox_id)
print("Sandbox connected", same_sbx.sandbox_id)
```

## List suspended sandboxes

You can call `Sandbox.list()` and pass in the status filter to list all suspended sandboxes. For more list query methods, please refer to [List Query](/docs/agent-sandbox/sandbox/list.md).

```python
from ucloud_sandbox import Sandbox, SandboxQuery, SandboxState

# Query all suspended sandboxes
paginator = Sandbox.list(
    query=SandboxQuery(state=[SandboxState.PAUSED]),
)

# Get the first page
sandboxes = paginator.next_items()

# Get the remaining pages
while paginator.has_next:
    items = paginator.next_items()
    sandboxes.extend(items)

for sbx in sandboxes:
    print("Sandbox paused", sbx.sandbox_id)
```

## Delete a suspended sandbox

If a suspended sandbox is no longer needed, call `kill()` to delete it. Once deleted, the sandbox cannot be restored.

```python
from ucloud_sandbox import Sandbox

sbx = Sandbox.create()
sbx.pause()

# Delete by instance
sbx.kill()

# You can also delete by sandbox ID
Sandbox.kill(sbx.sandbox_id)
```

## Sandbox timeout

When connecting to the sandbox, the timeout is reset. The default timeout is 5 minutes, you can also pass a custom timeout in `Sandbox.connect()`:

```python
from ucloud_sandbox import Sandbox

sbx = Sandbox.connect("your-sandbox-id", timeout=60) # 60 seconds
```

##Auto pause

Automatic suspension is enabled via lifecycle configuration when creating the sandbox. After setting `on_timeout` to `pause`, the sandbox will not be destroyed when it times out, but will automatically enter the paused state.

```python
from ucloud_sandbox import Sandbox

sandbox = Sandbox.create(
    timeout=10 * 60, # Optional: set the timeout to 10 minutes
    lifecycle={
        "on_timeout": "pause", # Automatically pause after timeout
        "auto_resume": False, # Optional, default value is False
    },
)
```

Auto-pause is a persistent configuration: if the sandbox times out again after being resumed, it will still automatically pause again.

If `.kill()` is called, the sandbox is permanently deleted and cannot be restored again.

## Network connection

If a process that provides external services, such as a web service, is running in the sandbox, the service will not be accessible from the outside after the sandbox is paused, and existing client connections will also be disconnected.

After restoring the sandbox, the service becomes accessible again; however, external clients need to reconnect.

## Limitations and Notes

### Pause and resume time consuming

- Pausing the sandbox takes approximately **4 seconds** per 1 GiB of memory
- Restoring the sandbox usually takes about **1 second**

### Sandbox retention time paused

- Paused sandboxes will remain until you actively delete them
- You can resume a suspended sandbox at any time later

### Continuous running limit

- The upper limit of a single continuous operation of the sandbox without pausing is **24 hours**
- After the sandbox is paused and resumed, the continuous running time will be recalculated
