# Snapshots

**Page:** foundation/containers/snapshots

[Download Raw Markdown](./foundation/containers/snapshots.md)

---

# Snapshots

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

After [creating](/foundation/containers/create-edit-delete/) and [managing](/foundation/containers/managing/) containers, you need **protection against mistakes** and the ability to **version your infrastructure**.

---

## API Endpoints Summary

**Official Technical Reference:**

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

**Snapshot Operations:**
- **[GET /api/v1/containers/\{id\}/snapshots](/api/container-snapshots/)** - List all snapshots
- **[POST /api/v1/containers/\{id\}/snapshots](/api/container-snapshots/)** - Create new snapshot
- **[PATCH /api/v1/containers/\{id\}/snapshots/\{name\}](/api/container-snapshots/)** - Restore from snapshot
- **[DELETE /api/v1/containers/\{id\}/snapshots/\{name\}](/api/container-snapshots/)** - Delete snapshot
- **[PATCH /api/v1/containers/\{id\}/snapshots/\{name\}/alias](/api/container-snapshots/)** - Update snapshot alias

**Related:**
- **[GET /api/v1/containers/\{id\}](/api/containers/)** - Container details
- **[POST /api/v1/containers/\{id\}/copy](/api/container-copy-sync/)** - Copy from specific snapshot

---

> **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](/foundation/hoody-api/authentication/), then `export HOODY_TOKEN=hdy_…` before running the curl snippets.

## What Are Snapshots?

**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)


**Snapshots are filesystem-only (stateless).** They capture the container's disk at a point in time — not RAM, not running processes, and not in-flight network connections. To guarantee a clean on-disk state for databases or apps holding data in memory, flush/stop them (or stop the container) before snapshotting.


**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


**In the AI era, snapshots are survival.** When AI generates code you can't review, snapshot before execution. If it breaks something, instant rollback. Experimentation becomes safe.


---

## Why Snapshots Matter

### The AI Safety Net

From [Understanding Hoody](/vision/obsolescence/):

> **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.**

### Real-World Protection

**Before risky changes:**



If something breaks, restore the snapshot:



**Before deployments:**

```bash
# 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
```

---

## Creating Snapshots

### Basic Snapshot Creation



**Response:**

```json
{
  "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).

### Snapshot Naming

**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"`

### Snapshot Expiration

**Snapshots can auto-delete after specified days:**

```bash
# 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

---

## Restoring Snapshots

**Revert container to any previous snapshot.**

### Basic Restore



**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.


**Restoration is destructive.** Current container state is lost. If you want to preserve current state, snapshot it first before restoring.


### Safe Restore Workflow


  
    ```bash
    # 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.**
  
  
    ```bash
    # Restore to previous snapshot
    curl -X PATCH "https://api.hoody.icu/api/v1/containers/{id}/snapshots/production-stable" \
      -H "Authorization: Bearer $HOODY_TOKEN"
    ```
  
  
    ```bash
    # Check container status
    curl "https://api.hoody.icu/api/v1/containers/{id}" \
      -H "Authorization: Bearer $HOODY_TOKEN"

    # Confirm status == "running" (or whatever state matches the snapshot)
    ```
  
  
    ```bash
    # Access via service URLs
    # https://{project}-{container}-terminal-1.{server}.containers.hoody.icu
    
    # Verify everything works as expected
    # If issues, restore to "before-restore" snapshot
    ```
  


---

## Listing Snapshots

**View all snapshots for a container:**



**Response:**

```json
{
  "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)

---

## What Snapshots Capture

**Snapshots are stateless (filesystem-only):**

```bash
# 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.


**Snapshotting a running container is safe**, but apps holding important data in memory (databases, queues) should flush to disk — or be stopped — first, so the captured filesystem is consistent.


---

## Deleting Snapshots

**Permanently remove snapshots to free storage:**



**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.

### When to Delete Snapshots

**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](/foundation/containers/copy-sync/))
- Historical reference (architecture decisions, configurations)

---

## Snapshot Strategies

### Strategy 1: Pre-Operation Safety

**Snapshot before every risky change:**

```bash
# 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.

### Strategy 2: Versioned Milestones

**Snapshot significant states:**

```bash
# 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.

### Strategy 3: Daily Automated Backups

```javascript
// 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.

### Strategy 4: Git-Style Branching

**Branch your infrastructure like Git:**

```bash
# 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.**

---

## Snapshot Operations

### List All Snapshots



**Returns chronological list** with details for each snapshot.

### Create Snapshot



**Both parameters optional:**
- No alias → Only auto-generated name
- No expiry → Permanent snapshot

### Restore Snapshot



**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 Snapshot



**Storage freed immediately.**

---

## Snapshot Size & Storage

**Snapshots consume storage based on container size:**

| Container Size | Snapshot 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 vs Container Copy

<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin: 1.5rem 0;">

<div style="padding: 1.25rem; background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;">

**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

</div>

<div style="padding: 1.25rem; background: #f8f8f8; border: 1px solid #ddd; border-radius: 4px;">

**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

</div>

</div>

**You can copy FROM snapshots:**

```bash
# 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](/foundation/containers/copy-sync/) for duplication workflows.

---

## Real-World Scenarios

### Scenario 1: Safe AI Experimentation


  
    ```bash
    # 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
    ```
  
  
    ```typescript
    // 1. Snapshot current working state
    await client.api.containers.createSnapshot(DEV_ID, {
      alias: 'working-baseline'
    });

    // 2. Let AI agent make changes...

    // 3. Changes work? Create new milestone
    await client.api.containers.createSnapshot(DEV_ID, {
      alias: 'with-ai-improvements'
    });

    // Or changes broke something? Restore baseline
    await client.api.containers.restoreSnapshot(DEV_ID, 'working-baseline');
    ```
  
  
    ```bash
    # 1. Snapshot current working state
    curl -X POST "https://api.hoody.icu/api/v1/containers/{dev_id}/snapshots" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"alias": "working-baseline"}'

    # 2. Let AI agent make changes...

    # 3. Changes work? Create new milestone
    curl -X POST "https://api.hoody.icu/api/v1/containers/{dev_id}/snapshots" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"alias": "with-ai-improvements"}'

    # Or changes broke something? Restore baseline
    curl -X PATCH "https://api.hoody.icu/api/v1/containers/{dev_id}/snapshots/working-baseline" \
      -H "Authorization: Bearer $HOODY_TOKEN"
    ```
  


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

### Scenario 2: Production Deployment with Rollback


  
    ```bash
    # 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
    ```
  
  
    ```typescript
    // Before deployment
    await client.api.containers.createSnapshot(PROD_ID, {
      alias: 'pre-deploy-v2.1.0',
      expiry: 30
    });

    // Deploy via terminal...

    // Issue detected! Rollback
    await client.api.containers.restoreSnapshot(
      PROD_ID, 'pre-deploy-v2.1.0'
    );
    // Production restored in 15 seconds
    ```
  
  
    ```bash
    # Before deployment
    curl -X POST "https://api.hoody.icu/api/v1/containers/{prod_id}/snapshots" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"alias": "pre-deploy-v2.1.0", "expiry": 30}'

    # Deploy via terminal/SSH
    # https://{project}-{prod_id}-terminal-1.{server}.containers.hoody.icu

    # Issue detected! Rollback
    curl -X PATCH "https://api.hoody.icu/api/v1/containers/{prod_id}/snapshots/pre-deploy-v2.1.0" \
      -H "Authorization: Bearer $HOODY_TOKEN"

    # Production restored in 15 seconds
    ```
  


### Scenario 3: Development Checkpoints

```bash
# 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.

### Scenario 4: Container Templates


  
    ```bash
    # 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"
    ```
  
  
    ```typescript
    // Snapshot as permanent template (omit `expiry` for no expiration)
    await client.api.containers.createSnapshot(TEMPLATE_ID, {
      alias: 'dev-template-2025'
    });

    // New developer joins? Copy from this snapshot
    await client.api.containers.copy(TEMPLATE_ID, {
      target_project_id: THEIR_PROJECT,
      name: 'new-dev-env',
      source_snapshot: 'snap-20251109-143045'
    });
    ```
  
  
    ```bash
    # Snapshot as permanent template
    curl -X POST "https://api.hoody.icu/api/v1/containers/{template_id}/snapshots" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"alias": "dev-template-2025"}'

    # New developer joins? Copy from this snapshot
    curl -X POST "https://api.hoody.icu/api/v1/containers/{template_id}/copy" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "target_project_id": "{their_project}",
        "name": "new-dev-env",
        "source_snapshot": "snap-20251109-143045"
      }'
    ```
  


**One perfect setup, infinite duplicates.**

---

## Snapshot Management

### List Snapshots



**Use the returned list to:**
- Monitor snapshot accumulation (`response.data.length`)
- Trigger cleanup when count is high
- Verify a specific snapshot exists before restore

### Cleanup Old Snapshots

```javascript
// 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.

---

## Snapshot Best Practices

### 1. Snapshot Before Destructive Operations

```bash
# ✅ 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
```

### 2. Use Descriptive Aliases

```bash
# ✅ 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.**

### 3. Set Appropriate Expiration


  
    ```json
    {
      "alias": "before-experiment",
      "expiry": 7
    }
    ```
    
    **Short experiments:** 7 days auto-cleanup
  
  
    ```json
    {
      "alias": "pre-deploy-v2.1.0",
      "expiry": 30
    }
    ```
    
    **After deployment verified (30 days):** Auto-delete
  
  
    ```json
    {
      "alias": "v1.0.0-stable"
    }
    ```

    **Major versions:** Omit `expiry` to keep permanently
  


### 4. Stop (or Quiesce) Before Snapshotting for Consistency

```bash
# 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.**

### 5. Verify Snapshots Exist

```bash
# 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).

---

## Integration Patterns

### With Container Copy

**Use snapshots as copy sources:**

```bash
# 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.**

### With Automated Deployment

```javascript
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.**

---

## Useful Questions

### How long does snapshot creation take?

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.

### Can I snapshot a running container?

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?

**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?

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.

### How many snapshots can I create?

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?

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?

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?

**Snapshot is instant state capture.** Backup is copying to external storage. Use snapshots for quick rollback (restore in seconds). Combine with [container copy](/foundation/containers/copy-sync/) to different servers for true disaster recovery.

### Can snapshots be encrypted?

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

---

## Troubleshooting

### Snapshot Creation Fails

**Problem:** Snapshot operation returns error

**Solutions:**

1. **Check storage usage:**
   ```bash
   GET /api/v1/containers/{id}
   # Verify container has available storage
   ```

2. **Check container status:**
   ```bash
   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

### Snapshot Restore Hangs

**Problem:** Restore operation doesn't complete

**Typical restore time:** 5-15 seconds for most containers

**If longer:**

1. **Check snapshot size:**
   ```bash
   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:**
   ```bash
   GET /api/v1/servers/{server_id}
   # Server status should be "active"
   ```

### Cannot Find Snapshot to Restore

**Problem:** Restore returns 404 Not Found

**Solutions:**

1. **Verify snapshot name (not alias):**
   ```bash
   # 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:**
   ```bash
   GET /api/v1/containers/{id}/snapshots
   # Verify snapshot still in list
   # Check expires_at hasn't passed
   ```

### Snapshots Consuming Too Much Storage

**Problem:** Snapshot storage costs are high

**Solutions:**

1. **Delete old/unused snapshots:**
   ```bash
   # 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:**
   ```bash
   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:
   ```bash
   # e.g. clean package caches / temp files inside the container, then:
   POST /api/v1/containers/{id}/snapshots
   ```

### 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

---

## What's Next

**Master container state management:**

1. **[Copy & Sync →](./copy-sync/)** - Duplicate containers, sync changes
2. **[Images →](./images/)** - Choose base OS and software
3. **[Create, Edit, Delete →](./create-edit-delete/)** - Container fundamentals

**Use snapshots with:**
- **[Managing Containers →](./managing/)** - Snapshot before stop/restart operations
- **[Network Configuration →](/foundation/networking/network/)** - Snapshot before network changes
- **[Firewall →](/foundation/networking/firewall/)** - Snapshot before firewall modifications

**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.**