Volumes

Persistent file storage mounted into functions and apps with rb.Volume.

Volumes give deployed code a persistent, shared filesystem — the natural home for model artifacts, feature files, and anything too large or too binary for run parameters. They mirror Modal's volumes: create one lazily, mount it at a path, read and write ordinary files.

import rebase as rb

vol = rb.Volume.from_name("model-cache", create_if_missing=True)


@rb.function(project="energy", volumes={"/models": vol})
def train(site_id: str = "site-001") -> dict:
    model = fit_model(site_id)
    with open("/models/site-001.pkl", "wb") as f:
        pickle.dump(model, f)
    return {"stored": "/models/site-001.pkl"}


@rb.function(project="energy", volumes={"/models": rb.Volume.from_name("model-cache", read_only=True)})
def predict(site_id: str = "site-001") -> dict:
    with open("/models/site-001.pkl", "rb") as f:
        model = pickle.load(f)
    return {"forecast": model.predict()}

Volumes attach to functions (all run types) and ASGI apps. Workflow steps execute inside the Prefect worker in v1 and cannot mount volumes yet.

Working with Files from Your Machine

The SDK moves bytes over presigned URLs — directly between you and object storage, never through the platform API:

vol = rb.Volume.from_name("model-cache")
vol.put_file("local/model.pkl", "site-001.pkl")
vol.put_directory("training-runs/", "runs")
vol.listdir()                       # [{"path": "site-001.pkl", "size": ..., "updated": ...}]
data = vol.read_file("site-001.pkl")
vol.get_file("site-001.pkl", "downloaded.pkl")
vol.remove_file("site-001.pkl")

The same operations are available from the CLI:

rebase volume create model-cache
rebase volume list
rebase volume ls model-cache
rebase volume put model-cache local/model.pkl site-001.pkl
rebase volume download model-cache site-001.pkl
rebase volume rm model-cache site-001.pkl
rebase volume delete model-cache        # removes the volume AND all files

Consistency Model

Volumes are backed by object storage (GCS in v1) mounted with gcsfuse. Writes are visible to other readers when the file is closed — there is no commit() step. Volume.commit() and Volume.reload() exist as no-ops for Modal compatibility.

Guidelines:

  • Treat files as whole objects: write-then-close, read-after-open. Appending and in-place mutation of large files perform poorly on FUSE-mounted object storage.
  • Concurrent writes to the same file are last-write-wins. Give concurrent writers distinct paths (e.g. one file per site or per run).
  • Mount read_only=True wherever code only reads — it is both safer and faster.

Storage Layout

Each workspace gets one storage bucket; each volume is a prefix inside it, and containers see only their own volume via scoped mounts. Volume records carry a provider field (gcs today) so alternative backends can be added without changing the SDK surface.

Deleting a volume deletes every file in it. There is no undelete.

On this page