A persistent disk preserves files written under its mount path across service restarts and deployments. The rest of the container filesystem remains disposable. Use a disk when your application needs local persistent files; use PostgreSQL or Key Value when you need those managed database capabilities.
Requirements and tradeoffs
- One disk per paid web service, private service, or background worker.
- No disks on free services, cron jobs, or static sites.
- A disk-backed service runs at most one instance and cannot use autoscaling.
- Deployments stop the old instance before starting its replacement. Plan for an interruption; this service no longer uses rolling updates.
- The disk is available to the running service, not its build or pre-deploy command. It is not a shared filesystem for other services.
- Bex's current API accepts sizes from 10 to 10,000 GB, defaulting to 10 GB. Storage can grow but cannot shrink.
Self-hosted installations need a working storage provisioner and control-plane service management. Snapshot and restore support additionally requires configured backup storage and encryption keys. A successful disk attachment does not prove that backups are configured or succeeding.
Attach a disk
In the service's Disks page, provide a name, absolute mount path, and size.
Choose a path used only for data, such as /var/data, and configure your
application to write there. Mounting a volume hides files already present at
that path in the image; it does not copy those files into the volume.
You can also declare a disk in a render.yaml Blueprint:
services:
- name: uploads-api
type: web
runtime: docker
repo: https://github.com/your-org/uploads-api
plan: starter
numInstances: 1
disk:
name: uploads
mountPath: /var/data
sizeGB: 10Replace the repository and choose an available paid plan. Validate and apply
through the Blueprint workflow. For an existing eligible service, the API
supports POST /v1/disks with serviceId, name, mountPath, and sizeGB.
The mount path must be absolute and cannot replace / or reserved platform
paths such as /etc, /etc/secrets, or /opt/render/project/src. Prefer a
separate data directory instead of mounting over your application or secrets.
Wait for the disk and service to become ready. Write a noncritical test file through the application, restart the service, and verify that the file remains before relying on the volume for production data.
Inspect and grow storage
Set BEX_API_URL to your API origin, BEX_TOKEN to an authorized token,
SERVICE_ID to the owning service, and DISK_ID to the returned disk id.
To find the service's disk:
curl --fail-with-body "$BEX_API_URL/v1/disks?serviceId=$SERVICE_ID" \
-H "Authorization: Bearer $BEX_TOKEN"To increase a 10 GB disk to 20 GB:
curl --fail-with-body -X PATCH "$BEX_API_URL/v1/disks/$DISK_ID" \
-H "Authorization: Bearer $BEX_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sizeGB":20}'A successful response records the requested size. Provisioner expansion and filesystem growth can finish later; a restart may be needed to finish filesystem expansion. Check capacity before writing into the additional space. Do not assume Render's documented online-growth timing applies to Bex's storage driver.
Changing the mount path changes where the same volume appears to the process. Update the application's data-path configuration with it. Increasing capacity does not relocate or clean up existing files.
Check snapshots before you need them
When configured, Bex schedules daily encrypted file-level snapshots into object storage and retains the seven newest snapshots. With successful daily backups, that gives approximately a week of restore points. These are filesystem archives, not application-consistent database backups. Inspect the available snapshots and practice recovery; do not infer a successful backup from the schedule alone.
curl --fail-with-body "$BEX_API_URL/v1/disks/$DISK_ID/snapshots" \
-H "Authorization: Bearer $BEX_TOKEN"If the API returns DISK_SNAPSHOTS_NOT_CONFIGURED, this installation has not
configured snapshot access. Ask the instance operator to configure it and
verify a completed backup. Each returned snapshotKey expires after 24 hours;
list again when you need a fresh restore key.
Restore a snapshot
Restoring replaces the disk's contents: writes made after the selected snapshot are lost, and the service is stopped for the restore. Export anything you need to retain before proceeding. For a database you manage on a service disk, use database-native backup and recovery tools instead of treating a filesystem snapshot as a consistent database backup.
Select the snapshot in the dashboard and review the destructive-action prompt.
API clients use POST /v1/disks/{diskId}/snapshots/restore with a JSON body
containing snapshotKey from the current list.
The API returns the disk after accepting the request; that response does not mean recovery is complete. Follow the service and restore status, wait for readiness, then verify both files and application behavior before resuming users or background processing.
Delete a disk
Disk deletion destroys its data and removes access from the service. Export a
backup you control first; do not rely on the disk's own snapshots surviving its
removal. Use the dashboard deletion control or DELETE /v1/disks/{diskId} only
after checking the owning service and id. Suspension is a different action and
does not delete storage.
Troubleshoot
Check the service's disk status and events. StorageBlockedByQuota indicates
insufficient storage quota; StorageClassNotExpandable indicates a provisioner
that cannot perform the requested growth; DiskResizePending can mean filesystem
expansion is waiting to complete. For permission errors, check the application's
runtime user and the mount directory. For disappearing files, confirm the
application actually wrote under the mounted path.
See Scaling, How deploys work, and App lifecycle for the operational effects of a disk. Platform etcd, OpenBao, Postgres archives, and Key Value RDB drills are a separate model — see Platform recovery.