Skip to content

User guideData and files

App storage

Durable volumes and object stores an administrator attaches to your app, which one to ask for, and how your code finds them.

View as Markdown

App storage is for files your app keeps: a database file, uploads, reports, exports. An administrator creates storage and attaches it to apps. You can’t attach it yourself unless an administrator made you a delegate of that storage.

Files your app only needs while it works go in scratch space instead. Scratch is there for every app, and it is wiped on every restart.

Volume Object store
What it is A real file system A folder in a bucket
Files can be Appended to, renamed, locked Read and written whole only
Use it for SQLite and DuckDB, caches, working files Datasets, model weights, exports, reports

If your app keeps a database file, ask for a volume. An object store has no append, no rename and no locking, so a database on one breaks.

The level is how the storage is attached to your app, not a permission your code asks for. Storage attached read only can’t be written to, whatever your code does.

Kind Levels
Volume Read only · Read & write
Object store Read only · Can add (new files only) · Can replace (also overwrite) · Can delete (also delete)

Some object stores can’t be attached at every level. Those levels aren’t offered when attaching.

Look storage up by its name, never by its path, so the administrator can move it without breaking your app. A name is lowercase letters, digits and hyphens, like sales-data, and it never changes. On your app’s Overview, each storage under Storage has a Code section with these calls already written for it, in Python, Node, R and Go.

import toft
reports = toft.storage("reports")
(reports.path / "2026-08.csv").write_bytes(data)
toft.store("exports").put("summary.csv", "2026-08/summary.csv") # copy a local file in
for m in toft.mounts():
print(m.name, m.kind, m.path, m.access, m.folder)

A miss raises an error that lists what is attached. The Node, Go and R SDKs have the same calls: see Files and scratch space.

On an install with no cluster an object store is not mounted, so it has no path. Your app reaches it with the SDK’s upload, download, url, remove and list calls instead, which also work everywhere else, and from the app’s jobs as well as from the app itself.

The same storage can be attached twice at different folders and levels, such as the root read-only and a drop folder writable. Both share a name, so name the folder:

toft.storage("warehouse", folder="") # the root
toft.storage("warehouse", folder="drop") # the writable folder

Your app’s access and yours are separate

Section titled “Your app’s access and yours are separate”

Neither implies the other. Your app having reports doesn’t let you browse it, and your grant gives your app nothing.

  • Changes reach your app on its next deploy or restart. Storage never appears or disappears under a running app.
  • Removing storage never deletes files. Detaching storage or deleting an app leaves the data in place.
  • On an install without a cluster, a volume needs a host directory set up by whoever runs Toft. Without one, deploying an app with a volume attached is refused.