MetorialDocs

Lifecycle, pausing, and hibernation

Control when sandbox machines pause or hibernate, and run hooks on every transition.

Machines don't need to run all the time. Pause a machine to freeze it exactly as it is, or hibernate it to stop using compute while its files stay on disk. Idle policies do this for you, and lifecycle hooks let your code react to each transition.

What you'll learn

  • The states a machine moves through
  • How pausing and hibernation differ
  • How to pause and hibernate idle machines automatically
  • How to run code on start, pause, resume, and terminate

Before you start

Machine states

Rendering diagram…

Transitions pass through short in-between states: pausing, resuming, hibernating, restarting, and terminating. A machine that can't boot ends up failed; its failure field says why (see Monitoring).

CommandEffect
startStarts a paused or hibernated machine
pauseFreezes a running machine, memory included
hibernateStops the machine; files on disk stay
restartBoots the machine again on a fresh instance
touchRecords activity so idle policies wait longer
deleteTerminates the machine and deletes its root disk
metorial-admin sandbox machines pause $MACHINE
metorial-admin sandbox machines start $MACHINE

Call start before you connect to a paused or hibernated machine.

Pause or hibernate?

Pausing keeps everything: memory, running processes, open files. When you start the machine again, it continues exactly where it stopped, and it does so faster than a cold boot. A paused machine still holds its memory, so keep pauses short.

Hibernation stops the machine. The root disk and attached disks keep every file, but processes are gone. Starting a hibernated machine boots it fresh, runs your setup commands and entrypoint, and fires start hooks.

Tip

For most agents, hibernation plus a good startup routine is the better choice. Write state to disk as you go, and let the entrypoint or a start hook bring services back up. An idle machine then uses no compute, and it comes back in a clean, known state. Use pausing for short breaks where an in-memory process can't be rebuilt quickly.

A machine that stays paused for a long time (8 hours or more) may be restarted by the platform. Set a hibernation policy so that happens on your terms.

Pause and hibernate idle machines automatically

A lifecycle policy moves idle machines along for you:

FieldWhat it does
pause_after_idle_secondsPause the machine after it's been idle this long
hibernate_after_paused_secondsHibernate the machine after it's been paused this long
connection_idle_secondsHow long a connection can go without traffic before it stops counting as activity

Set a field to null to turn it off. If pausing is off and hibernation is on, the machine hibernates directly once it has been idle for the hibernation time.

Activity is anything that uses the machine: an open shell, file, or port connection with traffic, or a touch call. A connection that's silent for connection_idle_seconds no longer keeps the machine awake.

This policy hibernates a machine after 10 minutes without activity, which suits most agent workloads:

metorial-admin sandbox machines update $MACHINE --lifecycle-policy '{
  "pause_after_idle_seconds": null,
  "hibernate_after_paused_seconds": 600,
  "connection_idle_seconds": 300
}'
await metorial.sandbox.machines.update(machine.id, {
  lifecyclePolicy: {
    pauseAfterIdleSeconds: null,
    hibernateAfterPausedSeconds: 600,
    connectionIdleSeconds: 300
  }
});

// Keep the machine awake during long work that doesn't use a connection
await metorial.sandbox.machines.touch(machine.id);

The machine object tells you what comes next: last_activity_at, pause_at, hibernates_at, and upcoming_events (pauses, hibernations, and restarts scheduled within the next hour).

Lifecycle hooks

Hooks run your code when a machine changes state. Each hook runs on one transition:

onRuns when
startThe machine boots: after create, when starting from hibernation, and after a restart
pauseThe machine is about to pause
resumeThe machine continues after a pause
terminateThe machine is about to be deleted

A hook is either a script inside the machine or an HTTP request to a port inside the machine:

  • wait: the transition waits for the hook to finish. Use it for hooks that must complete first, such as flushing state before a pause.
  • timeout_seconds: how long the hook may run before it counts as failed.
metorial-admin sandbox machines update $MACHINE --lifecycle-hooks-file hooks.json
await metorial.sandbox.machines.update(machine.id, {
  lifecycleHooks: [
    {
      type: 'script',
      on: 'start',
      path: '/app/bin/restore.sh',
      arguments: ['--from', '/data'],
      wait: true,
      timeoutSeconds: 60
    },
    {
      type: 'http',
      on: 'pause',
      port: 3000,
      path: '/hooks/flush',
      wait: true,
      timeoutSeconds: 30
    }
  ]
});

Images can ship their own hooks. Set ignore_image_hooks to true to skip them.

A good startup routine

Combine the runtime and hooks so a machine recovers on its own after every boot:

  • Bake dependencies into a custom image so boots stay fast.
  • Use runtime.setup for quick preparation, such as creating directories or writing config from environment variables.
  • Use the entrypoint for the long-running service your agent talks to.
  • Use a start hook for work that depends on saved state, such as restoring a checkout from an attached disk.
  • Keep anything you need after a hibernation on disk, never only in memory.