---
title: Volumes | Runware Docs
url: https://runware.ai/docs/serverless/volumes
description: Keep model weights out of the checkpointed filesystem so a cold start does not fetch them again.
relatedDocuments:
  - https://runware.ai/docs/serverless/writing-a-model
  - https://runware.ai/docs/serverless/deploying
  - https://runware.ai/docs/serverless/compute-and-scaling
---
## Introduction

A volume is **a directory that survives**. Everything else your app writes is part of the worker's checkpointed state, and that is a more expensive place to put a large file than it looks.

```bash
runware serverless deploy ./model.py --id my-app --gpu-type rtx-pro-6000 \
  --volume /root/.cache/huggingface
```

## Why this exists

Your app runs in a sandbox whose **filesystem is part of what gets checkpointed**. That is what lets a worker resume from a snapshot, and it is why the platform starts quickly.

It also means an unmounted download is charged twice. **It is copied into every checkpoint**, making each one larger and slower, **and it is fetched again on every cold start** that begins from scratch.

A volume takes the directory out of both. The weights live on **node-local storage beside the worker**, outside the checkpointed root, and a worker that finds them already there skips the download entirely.

> [!NOTE]
> This is the single biggest lever on cold-start time for a model with large weights. **Everything else you tune is smaller than skipping a fifteen-gigabyte download.**

## The mount path is the whole thing

A volume has **no name**. Its mount path is its identity, both to your code and to the node-local directory it is keyed by.

```json
{
  "volumes": [
    { "mountPath": "/root/.cache/huggingface" },
    { "mountPath": "/models" }
  ]
}
```

Nothing to create beforehand, nothing to look up, and nothing to reference by handle. **You name the path your code already opens** and the platform mounts it there.

## What the platform will reject

- **Absolute paths only**, matching `^/[A-Za-z0-9._/+@-]+$`, up to 2048 characters. Each component between the slashes is **at most 255 bytes**, which is the filesystem limit the mirrored directory has to satisfy.
- **Mounting `/` is rejected.** A volume is a directory inside the tree.
- **`/data/liquid-components` and `/data/liquid-large-data` are reserved by the platform.** Either path, anything under one (`/data/liquid-components/models`) and anything over one (`/data`) are refused. Overlap is judged by path component, so `/data/liquid-components-x` is a separate path and is accepted.
- **No duplicates and no overlaps.** `/models` and `/models/flux` together are a mistake rather than a merge, and the platform treats them as one.
- **At most 30 per app.**

**Every one of these is checked when the app is created.** A create that breaks one comes back `422` with a JSON pointer at the volume that caused it, such as `/volumes/1/mountPath`.

## They are fixed when the app is created

This is the constraint that catches people. **`--volume` is a create-time flag.** The update route accepts a name, a configuration, a source and secrets, and it does not accept volumes.

> [!WARNING]
> An app's volume set is fixed at creation, so there is no way to add, remove or move one afterwards. Passing `--volume` to a deploy on a live app **is an error, not an update**. Changing your mount layout means creating a new app.

The set is also **frozen into each version**, so a rollback restores the volume layout that version shipped with.

Decide the paths before the first deploy. The cost of getting it wrong lands **after a build you already waited for**.

## What belongs on one

Anything your app **downloads or generates at runtime and would rather do once**. A Hugging Face cache, weights pulled on first load, a compiled kernel cache, an index built at startup.

Anything you can bake into the image at build time should stay there. **A file that is already in the layer is already on the node**, and mounting it over adds a moving part for nothing.

```python
@serve
class FluxDev:
    def load(self) -> None:
        # HF_HOME points at the mounted volume, so the second worker
        # on this node finds the weights already on disk
        self.pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-dev")
```

**Point your library's cache at the mount path** with an [environment variable](https://runware.ai/docs/serverless/environment-variables) and it will do the rest. Most model libraries already respect one.