Skip to content

Snapshots are time travel for containers. Capture complete state at any moment, restore instantly, branch your computers like Git branches code.

After creating and managing containers, you need protection against mistakes and the ability to version your infrastructure.


Official Technical Reference:

This Foundation page explains snapshot concepts and workflows. For complete endpoint documentation:

Snapshot Operations:

Related:


Prerequisite — $HOODY_TOKEN. The HTTP examples on this page assume HOODY_TOKEN is exported to a valid Hoody bearer token. Create one with hoody auth login (short-lived JWT) or the long-lived automation token flow, then export HOODY_TOKEN=hdy_… before running the curl snippets.

A snapshot captures the complete state of a container at a specific moment:

Yesterday ──→ 3 hours ago ──→ 1 hour ago ──→ NOW
● ● ● ●

Each point = a snapshot. Restore to any moment. Everything on disk returns:

  • ✅ Entire filesystem (all files, exactly as they were)
  • ✅ Database files (data at that moment, as written to disk)
  • ✅ Configuration (config files, environment files written to disk)
  • ✅ Installed software (packages, dependencies)

Think of it as: Git for entire computers, not just code.

Powered by Copy-on-Write (CoW):

  • Instant creation - No need to copy entire filesystem
  • 💾 Space efficient - Only changed blocks are stored after snapshot
  • 🔄 Fast restoration - CoW enables rapid rollback to any point
  • 📦 Unlimited snapshots - Minimal storage overhead per snapshot

From Understanding Hoody:

Snapshot before AI rewrites code. Instant rollback if it breaks.
Snapshot before deployments. Restore everything in seconds.
Snapshot experiments. Branch computers like Git branches code.

Isolation + Time Travel = Security for the AI era.

Before risky changes:

POST Create a snapshot before AI refactor
/api/v1/containers/{container_id}/snapshots
Click "Run" to execute the request

If something breaks, restore the snapshot:

PATCH Restore from snapshot
/api/v1/containers/{container_id}/snapshots/{snapshot_name}
Click "Run" to execute the request

Before deployments:

Terminal window
# Production deployment in progress
POST /api/v1/containers/{prod_id}/snapshots
{"alias": "pre-deploy-2025-11-09-14-30"}
# Deploy...
# Issues in production?
PATCH /api/v1/containers/{prod_id}/snapshots/pre-deploy-2025-11-09-14-30
# Back to working state instantly

POST Create a new snapshot
/api/v1/containers/{container_id}/snapshots
Click "Run" to execute the request

Response:

{
"statusCode": 200,
"message": "Snapshot created successfully",
"data": {
"container_id": "890abcdef12345678901cdef",
"project_id": "67e89abc123def456789abcd",
"snapshot": {
"name": "snap-20251109-143045",
"alias": "production-stable",
"created_at": "2025-11-09T14:30:45.000Z",
"last_used_at": null,
"expires_at": "2026-02-07T14:30:45.000Z",
"stateful": false,
"size": 4589764321
}
}
}

Snapshot created instantly. Container continues running (or stopped—snapshots work in any state).

Auto-generated names:

  • Format: snap-YYYYMMDD-HHMMSS
  • Example: snap-20251109-143045
  • Unique, chronologically sortable

User-friendly aliases:

  • Optional human-readable name
  • Max 100 characters
  • Makes snapshots easier to identify
  • Example: "pre-deploy", "working-state", "before-ai-changes"

Snapshots can auto-delete after specified days:

Terminal window
# Expires in 30 days
POST /api/v1/containers/{id}/snapshots
{"alias": "temp-backup", "expiry": 30}
# Expires in 90 days
POST /api/v1/containers/{id}/snapshots
{"alias": "quarterly-backup", "expiry": 90}
# Never expires (omit the `expiry` field entirely)
POST /api/v1/containers/{id}/snapshots
{"alias": "permanent-baseline"}

After expiration:

  • Snapshot auto-deleted
  • Storage freed
  • Cannot be restored

Use expiration for:

  • Temporary experiment backups
  • Pre-deployment snapshots (delete after verification)
  • Automated cleanup of old backups

Revert container to any previous snapshot.

PATCH Restore container from snapshot
/api/v1/containers/{container_id}/snapshots/{snapshot_name}
Click "Run" to execute the request

What happens:

  1. Current container filesystem is discarded
  2. Snapshot’s filesystem is applied
  3. Container filesystem reverts to the snapshot
  4. On-disk configuration reverts to the snapshot
  5. Container starts fresh from the restored filesystem (processes do not resume mid-execution)

Restoration time: Typically 5-15 seconds depending on snapshot size.

Terminal window
# Capture "right now" before restoring
curl -X POST "https://api.hoody.icu/api/v1/containers/{id}/snapshots" \
-H "Authorization: Bearer $HOODY_TOKEN" \
-d '{"alias": "before-restore"}'

Now you can restore to EITHER state.


View all snapshots for a container:

GET List all snapshots for a container
/api/v1/containers/{container_id}/snapshots
Click "Run" to execute the request

Response:

{
"statusCode": 200,
"message": "Snapshots retrieved successfully",
"data": {
"container_id": "890abcdef12345678901cdef",
"project_id": "67e89abc123def456789abcd",
"snapshots": [
{
"name": "snap-20251109-143045",
"alias": "production-stable",
"created_at": "2025-11-09T14:30:45.000Z",
"last_used_at": "2025-11-09T16:15:00.000Z",
"expires_at": "2026-02-07T14:30:45.000Z",
"stateful": false,
"size": 4589764321
},
{
"name": "snap-20251108-100000",
"alias": "before-ai-refactor",
"created_at": "2025-11-08T10:00:00.000Z",
"last_used_at": null,
"expires_at": "2025-12-07T10:00:00.000Z",
"stateful": false,
"size": 4123456789
}
]
}
}

Key information:

  • name - Auto-generated identifier (used for restore/delete)
  • alias - Your friendly name
  • created_at - When snapshot was taken
  • last_used_at - When last used for restore/copy (null if never used)
  • expires_at - Auto-deletion date (null if permanent)
  • stateful - Whether a RAM/process state was captured. Hoody snapshots are filesystem-only, so this is always false.
  • size - Storage space used (in bytes)

Snapshots are stateless (filesystem-only):

Terminal window
# Works whether the container is running or stopped
POST /api/v1/containers/{id}/snapshots

Includes:

  • ✅ Filesystem (everything written to disk)
  • ❌ Running processes
  • ❌ RAM / memory state
  • ❌ In-flight network connections

The stateful field on every snapshot is false — Hoody snapshots do not capture a RAM dump.

Restoration: The container’s filesystem reverts to the snapshot, then the container starts fresh from that disk state. Processes do not resume mid-execution; anything that was only in memory at snapshot time is not restored.


Permanently remove snapshots to free storage:

DELETE Delete a snapshot
/api/v1/containers/{container_id}/snapshots/{snapshot_name}
Click "Run" to execute the request

What gets deleted:

  • Snapshot data (the captured filesystem state)
  • Snapshot metadata (alias, timestamps)
  • Storage space freed

Cannot be recovered. The snapshot reference name becomes invalid.

Delete snapshots when:

  • Expired temporary backups
  • Superseded by newer snapshots
  • Storage optimization needed
  • Old experiment branches no longer needed

Keep snapshots when:

  • Long-term disaster recovery
  • Compliance/audit requirements
  • Template for new containers (copy from snapshot)
  • Historical reference (architecture decisions, configurations)

Snapshot before every risky change:

Terminal window
# Before AI code generation
POST /api/v1/containers/{id}/snapshots
{"alias": "before-ai-gen-${timestamp}"}
# Before manual configuration
POST /api/v1/containers/{id}/snapshots
{"alias": "before-nginx-config"}
# Before dependency updates
POST /api/v1/containers/{id}/snapshots
{"alias": "before-npm-update"}

If anything breaks: Restore in seconds.

Snapshot significant states:

Terminal window
# Working features (permanent — no expiry field)
POST /api/v1/containers/{id}/snapshots
{"alias": "v1.0.0-stable"}
# Before major refactor
POST /api/v1/containers/{id}/snapshots
{"alias": "v1.0.0-before-refactor", "expiry": 90}
# After refactor complete (permanent — no expiry field)
POST /api/v1/containers/{id}/snapshots
{"alias": "v2.0.0-stable"}

Create version history for your infrastructure.

// Automated snapshot script (run via cron)
async function dailyBackup(containerId) {
const token = process.env.HOODY_TOKEN;
const date = new Date().toISOString().split('T')[0];
await fetch(
`https://api.hoody.icu/api/v1/containers/${containerId}/snapshots`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
alias: `daily-backup-${date}`,
expiry: 30 // Keep 30 days of dailies
})
}
);
console.log(`Backup created: daily-backup-${date}`);
}
// Run at 2 AM daily
dailyBackup('890abcdef12345678901cdef');

Combine with expiry: Old snapshots auto-delete, no manual cleanup needed.

Branch your infrastructure like Git:

Terminal window
# Main production state
POST /api/v1/containers/{prod_id}/snapshots
{"alias": "prod-main"}
# Experiment: Try new feature
POST /api/v1/containers/{prod_id}/snapshots
{"alias": "experiment-feature-x"}
# Work on feature...
# Feature works! Merge by making it the new main
POST /api/v1/containers/{prod_id}/snapshots
{"alias": "prod-main-v2"}
# Or feature failed? Restore to prod-main
PATCH /api/v1/containers/{prod_id}/snapshots/prod-main

Same container, multiple timelines.


GET List all snapshots
/api/v1/containers/{container_id}/snapshots
Click "Run" to execute the request

Returns chronological list with details for each snapshot.

POST Create a new snapshot
/api/v1/containers/{container_id}/snapshots
Click "Run" to execute the request

Both parameters optional:

  • No alias → Only auto-generated name
  • No expiry → Permanent snapshot
PATCH Restore from snapshot
/api/v1/containers/{container_id}/snapshots/{snapshot_name}
Click "Run" to execute the request

Use the snapshot’s name, as returned by GET /api/v1/containers/{id}/snapshots. The name is always the auto-generated snap-<timestamp> value (e.g. snap-20251109-143045), independent of any alias you set — the alias is separate metadata, not the restore key. List the snapshots first and pass the name field to the restore call.

DELETE Delete a snapshot
/api/v1/containers/{container_id}/snapshots/{snapshot_name}
Click "Run" to execute the request

Storage freed immediately.


Snapshots consume storage based on container size:

Container SizeSnapshot Size
10 GB filesystem~10 GB
50 GB filesystem~50 GB
100 GB filesystem~100 GB

Snapshots are filesystem-only, so size tracks the container’s on-disk usage (no RAM dump is stored).

Incremental snapshots:

  • First snapshot: Full size
  • Subsequent snapshots: Only changes (incremental)
  • Hoody optimizes storage automatically

Storage costs apply. Delete old snapshots to minimize expense.


Snapshots

Purpose: Time travel within container

Characteristics:

  • ✅ Instant creation (seconds)
  • ✅ Incremental storage
  • ✅ Built into container
  • ✅ Fast restoration
  • ❌ Tied to source container
  • ❌ Can’t run independently
  • ❌ Lost if container deleted

Use for:

  • Backup/restore
  • Experimenting safely
  • Rollback mechanism
  • Version milestones

Container Copy

Purpose: Duplicate entire container

Characteristics:

  • ✅ Independent container
  • ✅ Can run on different server
  • ✅ Can be in different project
  • ✅ Survives source deletion
  • ❌ Slower creation (minutes)
  • ❌ Full storage (no incremental)
  • ❌ More resources required

Use for:

  • Creating staging from prod
  • Disaster recovery (different server)
  • Team environments (same setup)
  • Production redundancy

You can copy FROM snapshots:

Terminal window
# Create container from specific snapshot
POST /api/v1/containers/{source_id}/copy
{
"target_project_id": "{project_id}",
"name": "restored-copy",
"source_snapshot": "snap-20251109-143045"
}

See: Copy & Sync for duplication workflows.


Terminal window
# 1. Snapshot current working state
hoody snapshots create --container $DEV_ID --alias "working-baseline"
# 2. Let AI agent make changes...
# 3. Changes work? Create new milestone
hoody snapshots create --container $DEV_ID --alias "with-ai-improvements"
# Or changes broke something? Restore baseline
hoody snapshots restore --container $DEV_ID --name working-baseline

AI can break things freely. You always have a way back.

Scenario 2: Production Deployment with Rollback

Section titled “Scenario 2: Production Deployment with Rollback”
Terminal window
# Before deployment
hoody snapshots create --container $PROD_ID \
--alias "pre-deploy-v2.1.0" --expiry 30
# Deploy via terminal/SSH...
# Issue detected! Rollback
hoody snapshots restore --container $PROD_ID --name pre-deploy-v2.1.0
# Production restored in 15 seconds
Terminal window
# Working on complex feature over days
# Create checkpoints at milestones
# Day 1: Database schema ready
POST /api/v1/containers/{dev_id}/snapshots
{"alias": "checkpoint-db-schema", "expiry": 7}
# Day 2: API endpoints complete
POST /api/v1/containers/{dev_id}/snapshots
{"alias": "checkpoint-api-done", "expiry": 7}
# Day 3: Frontend integrated
POST /api/v1/containers/{dev_id}/snapshots
{"alias": "checkpoint-frontend", "expiry": 7}
# Something breaks on Day 4?
# Restore to Day 3 checkpoint
PATCH /api/v1/containers/{dev_id}/snapshots/checkpoint-frontend

Time-limited snapshots: 7-day expiry means automatic cleanup.

Terminal window
# Snapshot as permanent template
hoody snapshots create --container $TEMPLATE_ID \
--alias "dev-template-2025"
# New developer joins? Copy from this snapshot
hoody containers copy $TEMPLATE_ID \
--target-project-id $THEIR_PROJECT \
--name "new-dev-env" \
--source-snapshot "snap-20251109-143045"

One perfect setup, infinite duplicates.


GET List all snapshots for a container
/api/v1/containers/{container_id}/snapshots
Click "Run" to execute the request

Use the returned list to:

  • Monitor snapshot accumulation (response.data.length)
  • Trigger cleanup when count is high
  • Verify a specific snapshot exists before restore
// Delete snapshots older than 30 days (except permanent ones)
async function cleanupSnapshots(containerId) {
const token = process.env.HOODY_TOKEN;
const headers = { 'Authorization': `Bearer ${token}` };
// Get all snapshots
const response = await fetch(
`https://api.hoody.icu/api/v1/containers/${containerId}/snapshots`,
{ headers }
);
const { snapshots } = await response.json().then(r => r.data);
// Find old, non-permanent snapshots
const thirtyDaysAgo = Date.now() - (30 * 24 * 60 * 60 * 1000);
for (const snapshot of snapshots) {
const createdTime = new Date(snapshot.created_at).getTime();
const isPermanent = snapshot.expires_at === null;
if (!isPermanent && createdTime < thirtyDaysAgo) {
await fetch(
`https://api.hoody.icu/api/v1/containers/${containerId}/snapshots/${snapshot.name}`,
{ method: 'DELETE', headers }
);
console.log(`Deleted old snapshot: ${snapshot.alias || snapshot.name}`);
}
}
}

Or use expiry parameter: Snapshots delete themselves automatically.


Terminal window
# ✅ Always snapshot before:
POST /api/v1/containers/{id}/snapshots
# Then:
- force-stop operations
- major configuration changes
- dependency updates (npm, apt, pip)
- database migrations
- letting AI modify code
- production deployments
Terminal window
# ✅ Good aliases (context-rich)
{"alias": "pre-deploy-v2.1.0-2025-11-09"}
{"alias": "before-database-migration"}
{"alias": "working-state-ai-approved"}
# ❌ Poor aliases (vague)
{"alias": "backup"}
{"alias": "test"}
{"alias": "snapshot1"}

Future you will thank present you.

{
"alias": "before-experiment",
"expiry": 7
}

Short experiments: 7 days auto-cleanup

4. Stop (or Quiesce) Before Snapshotting for Consistency

Section titled “4. Stop (or Quiesce) Before Snapshotting for Consistency”
Terminal window
# Before snapshotting a container with active databases/writes:
# 1. Stop container (or flush/quiesce the workload)
POST /api/v1/containers/{id}/stop
# 2. Create snapshot of a quiet, consistent filesystem
POST /api/v1/containers/{id}/snapshots
{"alias": "daily-backup"}
# 3. Restart if needed
POST /api/v1/containers/{id}/start

A quiet filesystem at snapshot time = a clean, consistent restore.

Terminal window
# Before relying on restore, verify snapshot exists
curl "https://api.hoody.icu/api/v1/containers/{id}/snapshots" \
-H "Authorization: Bearer $HOODY_TOKEN" \
| grep "production-stable"

Don’t assume old snapshots still exist (may have expired or been deleted).


Use snapshots as copy sources:

Terminal window
# 1. Snapshot production
POST /api/v1/containers/{prod_id}/snapshots
{"alias": "prod-stable-2025-11-09"}
# 2. Copy to staging from this snapshot
POST /api/v1/containers/{prod_id}/copy
{
"target_project_id": "{staging_project}",
"name": "staging-env",
"source_snapshot": "snap-20251109-143045"
}

Staging gets exact production state from specific snapshot.

async function deployWithSafety(containerId, deployScript) {
const token = process.env.HOODY_TOKEN;
const headers = { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' };
// 1. Pre-deploy snapshot
const snapshot = await fetch(
`https://api.hoody.icu/api/v1/containers/${containerId}/snapshots`,
{
method: 'POST',
headers,
body: JSON.stringify({
alias: `pre-deploy-${Date.now()}`,
expiry: 7
})
}
).then(r => r.json());
try {
// 2. Execute deployment
await deployScript();
// 3. Health check
const health = await checkHealth(containerId);
if (!health.ok) {
throw new Error('Health check failed');
}
// 4. Success - create "deployed" snapshot
await fetch(
`https://api.hoody.icu/api/v1/containers/${containerId}/snapshots`,
{
method: 'POST',
headers,
body: JSON.stringify({
alias: `deployed-${Date.now()}`,
expiry: 30
})
}
);
return { success: true };
} catch (error) {
// 5. Failure - restore snapshot
console.error('Deployment failed, rolling back...', error);
await fetch(
`https://api.hoody.icu/api/v1/containers/${containerId}/snapshots/${snapshot.data.snapshot.name}`,
{ method: 'PATCH', headers }
);
return { success: false, error, rolledBack: true };
}
}

Deployment safety net built-in.


Nearly instant (1-5 seconds for filesystem metadata) thanks to Copy-on-Write. Your container keeps running during the snapshot — only the on-disk state is captured.

Yes! Snapshots work on any container state (running, stopped, paused). In every case the snapshot is filesystem-only — it captures the disk, not running processes or RAM. For the most consistent capture of in-memory data, flush or stop the workload first.

What happens to snapshots when I delete the container?

Section titled “What happens to snapshots when I delete the container?”

Snapshots are preserved. Deleting a container does NOT delete its snapshots. You can still use them to create new containers via copy operation. Orphaned snapshots remain until you explicitly delete them.

Can I restore a snapshot to a different container?

Section titled “Can I restore a snapshot to a different container?”

Not directly via restore operation. But you can copy a container from a specific snapshot to create a new container with that snapshot’s state. Use source_snapshot parameter in copy operation.

No hard limit. Practical limit: storage quota and cost. Recommend: 5-10 recent snapshots + permanent milestones. Use expiry to automate cleanup.

Do snapshots include proxy aliases and permissions?

Section titled “Do snapshots include proxy aliases and permissions?”

No. Snapshots capture container filesystem state only. Proxy aliases and permissions are configured separately at the proxy level. After restoring, you may need to reconfigure aliases.

Can I snapshot multiple containers simultaneously?

Section titled “Can I snapshot multiple containers simultaneously?”

Yes. Snapshots are independent HTTP operations. Snapshot 100 containers in parallel to capture multi-container application state.

What’s the difference between snapshot and backup?

Section titled “What’s the difference between snapshot and backup?”

Snapshot is instant state capture. Backup is copying to external storage. Use snapshots for quick rollback (restore in seconds). Combine with container copy to different servers for true disaster recovery.

Snapshots use container’s underlying storage encryption (if configured). For additional security, encrypt sensitive data at application level before snapshotting.


Problem: Snapshot operation returns error

Solutions:

  1. Check storage usage:

    Terminal window
    GET /api/v1/containers/{id}
    # Verify container has available storage
  2. Check container status:

    Terminal window
    GET /api/v1/containers/{id}
    # status should be running or stopped, not failed/creating
  3. Verify permissions:

    • Ensure you own the container
    • Check auth token is valid

Problem: Restore operation doesn’t complete

Typical restore time: 5-15 seconds for most containers

If longer:

  1. Check snapshot size:

    Terminal window
    GET /api/v1/containers/{id}/snapshots
    # Large snapshots (>100 GB) take longer
  2. Wait longer for large snapshots (up to 2-3 minutes)

  3. Check server status:

    Terminal window
    GET /api/v1/servers/{server_id}
    # Server status should be "active"

Problem: Restore returns 404 Not Found

Solutions:

  1. Verify snapshot name (not alias):

    Terminal window
    # List snapshots to get exact name
    GET /api/v1/containers/{id}/snapshots
    # Use the "name" field (snap-20251109-143045)
    # NOT the "alias" field (production-stable)
  2. Check snapshot didn’t expire:

    Terminal window
    GET /api/v1/containers/{id}/snapshots
    # Verify snapshot still in list
    # Check expires_at hasn't passed

Problem: Snapshot storage costs are high

Solutions:

  1. Delete old/unused snapshots:

    Terminal window
    # List snapshots sorted by age
    GET /api/v1/containers/{id}/snapshots
    # Delete snapshots never used for restore
    DELETE /api/v1/containers/{id}/snapshots/{old_snapshot_name}
  2. Set expiration on new snapshots:

    Terminal window
    POST /api/v1/containers/{id}/snapshots
    {"alias": "temp-backup", "expiry": 7}
  3. Trim the container filesystem before snapshotting (clear caches, logs, build artifacts) to reduce snapshot size:

    Terminal window
    # e.g. clean package caches / temp files inside the container, then:
    POST /api/v1/containers/{id}/snapshots

Restored Container Different Than Expected

Section titled “Restored Container Different Than Expected”

Problem: After restore, container state doesn’t match memory

Possible causes:

  1. Restored wrong snapshot:

    • Verify the snapshot name/alias passed to the restore operation
    • Re-list snapshots and confirm the intended one was targeted
  2. Snapshots are filesystem-only:

    • Running processes and in-memory state are never included
    • Only the filesystem is restored
    • Container starts fresh from that filesystem
  3. Post-snapshot changes:

    • Snapshot only captures THAT moment
    • Changes after snapshot aren’t included
    • Verify snapshot created_at timestamp

Master container state management:

  1. Copy & Sync → - Duplicate containers, sync changes
  2. Images → - Choose base OS and software
  3. Create, Edit, Delete → - Container fundamentals

Use snapshots with:

Understanding gained:

  • ✅ Snapshots capture the container’s filesystem (stateless, no RAM/process state)
  • ✅ Restore reverts the disk to any previous moment, then starts fresh
  • ✅ Expiration enables automatic cleanup
  • ✅ Snapshots survive container deletion
  • ✅ Can copy containers from snapshots
  • ✅ Incremental storage optimization

Snapshot before AI changes.
Snapshot before deployments.
Snapshot before experiments.
Instant rollback. Always safe. Time travel for computers.