Skip to content
Hoody.com

A snapshot records a container’s filesystem at a point in time: every file on its own storage, including database rows, config, logs, installed packages and environment files. It does not record memory or running processes, and it does not cover storage mounted from elsewhere, such as a share whose source is another container. Rather than a diff of selected paths, it is the complete disk state of the machine, frozen at a moment and restorable with one API call.

You do not decide what to include, write migration scripts, or track what changed. A button press or a single API call preserves the container’s own storage, and another puts it back. Restoring puts back that storage along with the container’s recorded configuration and devices: a container that was running is stopped and started again, so expect a short interruption, and one that was stopped stays stopped; anything outside that storage, such as a shared mount, a remote API call the container already made, or a credential it disclosed, is not reversed.


Every snapshot records the complete filesystem state of a container:

ComponentCapturedWhat it means
FilesystemFiles, directories, permission bitsCode, configs, logs, and data, exactly as they were
DatabasesData, tables, indexesSQLite files and PostgreSQL data directories, byte-identical on disk
Installed softwareapt packages, npm modules, binariesRestored at their exact versions, nothing to reinstall
EnvironmentEnvironment files, shell configs, crontabsThe on-disk runtime context is preserved
Network configDNS settings, routing table, proxy configurationOn-disk network configuration is identical after restore

If it is written to the container’s own disk, the snapshot captures it. Mounted shares belong to their source, and memory and in-flight work are not captured.


Hoody uses Copy-on-Write (CoW) at the filesystem level. When you create a snapshot, Hoody does not copy the entire disk. It marks the current filesystem state as immutable and begins tracking changes. Only new or modified blocks are stored separately.

This means:

  • Fast creation. A snapshot marks the current state rather than copying the disk, so creation cost does not grow with container size; nothing is copied or compressed.
  • Minimal storage. The first snapshot references the existing filesystem, and each later snapshot stores only the delta. Ten snapshots of a 50GB container do not cost 500GB; they cost 50GB plus the changes.
  • Frequent snapshots. The per-snapshot overhead is small enough to snapshot every commit, deployment, or experiment. Per-container snapshot caps apply (higher on rented servers than on the free tier), and expiring snapshots clean themselves up.
  • Whole-machine restore. Restoring a snapshot returns the container to the captured state exactly, in one API call, with no migration scripts and no partial state. How long it takes depends on the container.
Snapshot 1 (baseline) ──→ Full filesystem reference
Snapshot 2 (after AI) ──→ Delta: 47 files changed
Snapshot 3 (after deploy)──→ Delta: 12 files changed
Snapshot 4 (new feature) ──→ Delta: 89 files changed
Total storage: baseline + 148 files of changes
NOT: 4 full copies of the filesystem

AI generates code you cannot fully review. An LLM rewrites your authentication module: it looks correct at a glance and passes the tests you thought to write, but a subtle change in how sessions are invalidated slips past code review. Three days later you notice stale sessions. Two days after that, you trace them to the AI’s rewrite, and a week of development now sits on top of the bug.

Without a snapshot, that means reconstructing a week of changes by hand. With one, you restore before-ai-auth-rewrite, compare the two states, fix the specific issue, and move on.

Terminal window
# Before letting AI touch your code
SNAPSHOT_NAME=$(hoody snapshots create -c "$CONTAINER_ID" \
--alias "before-ai-refactor" -o json | jq -r '.snapshot.name')
# AI makes its changes...
# If something breaks, restore. Restore prompts for confirmation, and in a
# script the prompt resolves to "no", so pass -y when you mean it.
hoody snapshots restore -c "$CONTAINER_ID" --name "$SNAPSHOT_NAME" -y
# Back to exactly where you were

Snapshot before every AI interaction. Creating one takes seconds, and having one can save hours of debugging.


Git lets you branch code so an experiment cannot damage the main line. Snapshots bring the same workflow to the whole container.

Main state (snapshot: "production-stable")
│
├──→ Experiment A: try new database schema
│ Result: works. Create snapshot "with-new-schema"
│
├──→ Experiment B: try different AI model
│ Result: failed. Restore to "production-stable"
│
└──→ Experiment C: try new auth system
Result: promising. Create snapshot "auth-v2-wip"

Everything happens on the same container, with nothing to clone, provision, or wait for. You are not creating new machines; you are recording states of one machine and moving between them.

Terminal window
# Save the current state
SNAPSHOT_NAME=$(hoody snapshots create -c $CONTAINER_ID \
--alias "main-branch" -o json | jq -r '.snapshot.name')
# Experiment: try a risky database migration
hoody terminal commands run -c $CONTAINER_ID --ephemeral \
--command "python3 migrate.py --destructive"
# If it worked: save the result
hoody snapshots create -c $CONTAINER_ID --alias "after-migration"
# If it failed: restore and try something else (use the exact `name` returned by create/list)
hoody snapshots restore -c $CONTAINER_ID --name "$SNAPSHOT_NAME" -y

Snapshots turn deployments into reversible operations. Capture the state before you deploy, verify the result, and restore if verification fails.

1. Snapshot: POST /api/v1/containers/{prod}/snapshots
{"alias": "pre-deploy-v2.1.0", "expiry": 30}
2. Deploy: Execute your deployment scripts
3. Verify: Health checks, smoke tests, monitoring
4. Success: Delete the snapshot after 30 days (or let it expire)
5. Failure: PUT /api/v1/containers/{prod}/snapshots/{SNAPSHOT_NAME}
(the exact `name` returned by the create response)
Production restored to the pre-deploy state

A restore does not mean rolling back the code, re-running migrations, and hoping the data is consistent. It rolls back everything at once, in one API call: code, config, data, installed packages, the entire disk state.

Terminal window
# Before deployment
SNAPSHOT_NAME=$(hoody snapshots create -c $PROD_CONTAINER \
--alias "pre-deploy-v2.1.0" \
--expiry 30 -o json | jq -r '.snapshot.name')
# Deploy
hoody terminal commands run -c $PROD_CONTAINER --ephemeral \
--command "./deploy.sh v2.1.0"
# Verify
hoody terminal commands run -c $PROD_CONTAINER --ephemeral \
--command "curl -s localhost:3000/health | jq .status"
# If failed: roll back (use the exact `name` from the create output)
hoody snapshots restore -c $PROD_CONTAINER --name "$SNAPSHOT_NAME" -y

Something broke, but you are not sure when. With snapshots at regular intervals, you can binary-search for the change:

Monday snapshot: working
Tuesday snapshot: working
Wednesday snapshot: BROKEN

Restore Tuesday’s snapshot and confirm it still works: the bug was introduced between Tuesday and Wednesday. If you keep hourly snapshots, narrow the window to an hour, then compare the two states to find the exact change.

The bug might be in a config file, an environment variable, a system package update, or a cron job that ran at 3 AM. Everything on disk is in the snapshot, so the search covers the whole machine rather than only the source tree.


Terminal window
# Create with alias
hoody snapshots create -c $CONTAINER_ID --alias "milestone-v1"
# Create with expiration (auto-delete after 7 days)
hoody snapshots create -c $CONTAINER_ID \
--alias "temp-experiment" \
--expiry 7
# Create permanent snapshot (no expiration)
hoody snapshots create -c $CONTAINER_ID \
--alias "golden-image"
Terminal window
# List all snapshots for a container
hoody snapshots list -c $CONTAINER_ID

Restore returns 409 while the container’s network policy is still pending, with Container has no network policy in force and cannot be restored from a snapshot. Configure its network first, then retry. Restore also reapplies the container’s current API-managed environment variables afterwards, and the call returns without waiting for that.

Terminal window
# Restore from a snapshot (use the exact `name` returned by create/list).
# The CLI asks you to confirm; add -y when running it unattended.
hoody snapshots restore -c $CONTAINER_ID --name "$SNAPSHOT_NAME"
Terminal window
# Delete a snapshot to free storage.
# The CLI asks you to confirm; add -y when running it unattended.
hoody snapshots delete -c $CONTAINER_ID --name "$SNAPSHOT_NAME"

Snapshot before every AI task and set the expiry to 7 days. If the AI’s changes survive a week of use, the snapshot deletes itself. If something surfaces before then, you have the week to catch it.

Terminal window
# Alias pattern: before-ai-{task}-{date}
POST /api/v1/containers/{id}/snapshots
{"alias": "before-ai-auth-rewrite-2026-03-04", "expiry": 7}

Snapshot before and after every deployment. Keep the “before” for 30 days (rollback window). Keep the “after” permanently if the version is a major release.

Terminal window
# Before deploy: temporary
{"alias": "pre-deploy-v2.1.0", "expiry": 30}
# After deploy (major version): permanent
{"alias": "v2.0.0-stable"}

Use cron or hoody-cron to snapshot every container daily. Set expiry to 30 days. You always have a month of daily restore points, and old snapshots clean themselves up.

Set up a development environment once and snapshot it permanently. When a new team member joins, copy the container from that snapshot. One golden image produces as many copies as you need.

Terminal window
# The golden image: never expires
{"alias": "dev-template-2026-q1"}
# New team member:
POST /api/v1/containers/{template}/copy
{"target_project_id": "...", "name": "alice-dev", "source_snapshot": "dev-template-2026-q1"}

When a container is compromised:

  1. Snapshot the compromised state for forensic analysis
  2. Restore the last known-good snapshot so production runs from a clean state
  3. Compare the two snapshots to identify exactly what changed: which files were modified, which files and packages were added or changed
  4. Delete the compromised snapshot after analysis

You keep the filesystem evidence: the attacker’s changes stay in a snapshot for later study while you restore a clean state. Restoring interrupts the container, so serve from a second one if you must stay up, and remember that a disk snapshot records the disk, not running processes or network traffic. The whole sequence is a handful of API calls.


Git versions code. Snapshots version everything else.

GitSnapshots
Source codeYesYes
Database stateNoYes
System configurationPartially (dotfiles)Yes (all of /etc)
Installed packagesNo (requires rebuild)Yes (exact binary state)
Environment filesNo (.env in .gitignore)Yes
On-disk app/browser dataNoYes
Network configurationNoYes
RestoreRebuild (clone + install + build + migrate)One API call

Git versions what you wrote and snapshots version what you run; together they cover the entire stack.


Next: Realms & Projects explains how containers are organized.