> ## Documentation Index
> Fetch the complete documentation index at: https://docs.specific.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Volumes

> Persistent directories that survive deploys and restarts.

Volumes provide a directory that persists across deployments and restarts, useful for file uploads, caches, and other data that needs to survive.

Volumes are defined as sub-blocks within a service. Each volume has a name and exposes a `path` attribute that resolves to the directory path:

```hcl specific.hcl theme={null}
service "api" {
  build = build.api
  command = "node server.js"

  volume "uploads" {}

  env = {
    UPLOADS_DIR = volume.uploads.path
  }
}
```

## Attributes

| Attribute | Description                            |
| --------- | -------------------------------------- |
| `path`    | Absolute path to the volume directory. |

## How it works

* **In production**: each volume is backed by a persistent disk, and `path` resolves to `/volumes/{name}` inside the container.
* **In development** (`specific dev`): each volume maps to a local directory at `.specific/keys/.../data/volumes/{service}/{name}/`.

Volume data persists across deployments and dev server restarts.

## Multiple volumes

A service can define multiple volumes:

```hcl specific.hcl theme={null}
service "api" {
  build = build.api
  command = "node server.js"

  volume "uploads" {}
  volume "cache" {}

  env = {
    UPLOADS_DIR = volume.uploads.path
    CACHE_DIR   = volume.cache.path
  }
}
```

## Example usage (Node.js)

```javascript theme={null}
import fs from "fs";
import path from "path";

const uploadsDir = process.env.UPLOADS_DIR;

// Write a file
fs.writeFileSync(path.join(uploadsDir, "myfile.txt"), "Hello, world!");

// Read it back (persists across restarts)
const content = fs.readFileSync(path.join(uploadsDir, "myfile.txt"), "utf8");
```

## Preview environments

[Preview environments](/guides/previews) get an instant copy-on-write clone of each volume, so a preview's service starts on an exact copy of the parent's data with no extra configuration, and writes to the clone never affect the parent.
