Render Persistent Disks
Persistent disks are high-performance SSDs you attach to a Render service to preserve filesystem changes across deploys and restarts. Without a disk, services have an ephemeral filesystem—all local file changes are lost on every deploy.
When to Use
- Storing file uploads, CMS media, or user-generated content
- Running a self-managed database (MySQL, MongoDB, ClickHouse) on Render
- Deploying stateful infrastructure (Elasticsearch, Kafka, RabbitMQ, Mattermost)
- Understanding why scaling is blocked or zero-downtime deploys are disabled
- Restoring data from an automatic disk snapshot
For managed databases, prefer Render Postgres (render-postgres) or Key Value (render-keyvalue) over self-managed alternatives on disk.
Critical Constraints
These constraints affect architecture decisions. Understand them before attaching a disk:
| Constraint |
Impact |
| Single instance only |
Cannot scale horizontally (numInstances must be 1, autoscaling not available) |
| No zero-downtime deploys |
Old instance stops before new instance starts (brief downtime on each deploy) |
| Runtime access only |
Disk is not available during buildCommand or preDeployCommand (those run on separate compute) |
| Not accessible from other services |
Only the attached service can read/write the disk |
| Not available on cron jobs |
Attach to a web service, private service, or background worker instead |
| Not available on one-off jobs |
One-off jobs run on separate compute without disk access |
| Can increase size, cannot decrease |
Start small and grow as needed |
Setup
Dashboard
- Go to your service's Disks page
- Set the mount path (absolute path where persistent data is stored)
- Choose a size in GB
- Click Add disk — triggers a new deploy
Blueprint
services:
- type: web
name: cms
runtime: node
plan: starter
region: oregon
buildCommand: npm ci && npm run build
startCommand: npm start
disk:
name: cms-data
mountPath: /var/data
sizeGB: 10
Mount Path
Only files written under the mount path are preserved. Everything else remains ephemeral.
| Runtime |
Source code path |
Example mount path |
| Node.js, Python, Ruby, Elixir, Rust |
/opt/render/project/src |
/opt/render/project/src/uploads |
| Go |
/opt/render/project/go/src/github.com/<user>/<repo> |
.../data |
| Docker |
Dockerfile's WORKDIR (commonly /app) |
/app/storage |
Disallowed mount paths
Cannot mount at: /, /opt, /opt/render, /opt/render/project, /opt/render/project/src, /home, /home/render, /etc, /etc/secrets.
Subdirectories of these paths are fine (e.g. /opt/render/project/src/uploads).
Snapshots
- Render creates an automatic snapshot every 24 hours
- Snapshots are available for at least 7 days
- Restore from the service's Disks page in the Dashboard
- Full restore only — you cannot restore individual files
- Destructive — all changes after the snapshot are lost
Do not restore snapshots for custom database recovery. Use database-native backup tools (mysqldump, mongodump) instead—disk snapshots may capture a corrupted database state.
File Transfers
SCP (via SSH)
# Download from service
scp -s YOUR_SERVICE@ssh.YOUR_REGION.render.com:/mount/path/file ./local-file
# Upload to service
scp -s ./local-file YOUR_SERVICE@ssh.YOUR_REGION.render.com:/mount/path/file
Requires SSH access enabled for the service.
Magic-Wormhole
Available on all native runtimes (install manually on Docker):
# On the service shell
wormhole send /mount/path/file
# On your local machine
wormhole receive
Common Patterns
| Pattern |
Service type |
Mount path |
Notes |
| WordPress / Ghost / CMS |
Web Service |
/var/data or /app/content |
Media uploads, SQLite |
| Self-managed MySQL |
Private Service |
/var/lib/mysql |
Use mysqldump for backups, not disk snapshots |
| File upload API |
Web Service |
/opt/render/project/src/uploads |
Single instance constraint |
| Elasticsearch |
Private Service |
/usr/share/elasticsearch/data |
Stateful search infrastructure |
Common Mistakes
| Mistake |
Fix |
| Expecting horizontal scaling with a disk |
Not possible — disk services are single-instance only |
| Mounting at a disallowed path |
Use a subdirectory (e.g. /opt/render/project/src/uploads not /opt/render/project/src) |
| Reading disk during build or pre-deploy |
These run on separate compute — move logic to the start command |
| Restoring disk snapshot for a database |
Use database-native backups instead |
| Starting with a large disk size |
Start small — you can increase but never decrease |
References
| Document |
Contents |
references/sizing-and-snapshots.md |
Sizing guidance, snapshot lifecycle, restore procedures, cost patterns |
Related Skills
- render-web-services — Deploy lifecycle, health checks (disk disables zero-downtime)
- render-private-services — Internal services with disks (Elasticsearch, MySQL)
- render-blueprints —
disk field reference in render.yaml
- render-postgres — Managed database alternative (no disk management needed)
1---2name: render-disks3description: Attaches and manages persistent disks on Render services—mount paths, sizing, snapshots, file transfers, and single-instance constraints. Use when the user needs persistent storage, file uploads, a custom database on disk, CMS media storage, or needs to understand why their service can't scale horizontally or use zero-downtime deploys. Trigger terms: persistent disk, disk, storage, mount path, sizeGB, SSD, file uploads, snapshots, disk restore, ephemeral filesystem.4license: MIT5---67# Render Persistent Disks89Persistent disks are high-performance SSDs you attach to a Render service to preserve filesystem changes across deploys and restarts. Without a disk, services have an **ephemeral filesystem**—all local file changes are lost on every deploy.1011## When to Use1213- Storing **file uploads**, CMS media, or user-generated content14- Running a **self-managed database** (MySQL, MongoDB, ClickHouse) on Render15- Deploying **stateful infrastructure** (Elasticsearch, Kafka, RabbitMQ, Mattermost)16- Understanding **why scaling is blocked** or **zero-downtime deploys are disabled**17- **Restoring data** from an automatic disk snapshot1819For managed databases, prefer **Render Postgres** (render-postgres) or **Key Value** (render-keyvalue) over self-managed alternatives on disk.2021## Critical Constraints2223These constraints affect architecture decisions. Understand them **before** attaching a disk:2425| Constraint | Impact |26|------------|--------|27| **Single instance only** | Cannot scale horizontally (`numInstances` must be 1, autoscaling not available) |28| **No zero-downtime deploys** | Old instance stops before new instance starts (brief downtime on each deploy) |29| **Runtime access only** | Disk is not available during `buildCommand` or `preDeployCommand` (those run on separate compute) |30| **Not accessible from other services** | Only the attached service can read/write the disk |31| **Not available on cron jobs** | Attach to a web service, private service, or background worker instead |32| **Not available on one-off jobs** | One-off jobs run on separate compute without disk access |33| **Can increase size, cannot decrease** | Start small and grow as needed |3435## Setup3637### Dashboard38391. Go to your service's **Disks** page402. Set the **mount path** (absolute path where persistent data is stored)413. Choose a **size** in GB424. Click **Add disk** — triggers a new deploy4344### Blueprint4546```yaml47services:48 - type: web49 name: cms50 runtime: node51 plan: starter52 region: oregon53 buildCommand: npm ci && npm run build54 startCommand: npm start55 disk:56 name: cms-data57 mountPath: /var/data58 sizeGB: 1059```6061## Mount Path6263Only files written **under the mount path** are preserved. Everything else remains ephemeral.6465| Runtime | Source code path | Example mount path |66|---------|------------------|--------------------|67| Node.js, Python, Ruby, Elixir, Rust | `/opt/render/project/src` | `/opt/render/project/src/uploads` |68| Go | `/opt/render/project/go/src/github.com/<user>/<repo>` | `.../data` |69| Docker | Dockerfile's `WORKDIR` (commonly `/app`) | `/app/storage` |7071### Disallowed mount paths7273Cannot mount at: `/`, `/opt`, `/opt/render`, `/opt/render/project`, `/opt/render/project/src`, `/home`, `/home/render`, `/etc`, `/etc/secrets`.7475Subdirectories of these paths are fine (e.g. `/opt/render/project/src/uploads`).7677## Snapshots7879- Render creates an **automatic snapshot every 24 hours**80- Snapshots are available for **at least 7 days**81- Restore from the service's **Disks** page in the Dashboard82- **Full restore only** — you cannot restore individual files83- **Destructive** — all changes after the snapshot are lost8485**Do not restore snapshots for custom database recovery.** Use database-native backup tools (mysqldump, mongodump) instead—disk snapshots may capture a corrupted database state.8687## File Transfers8889### SCP (via SSH)9091```bash92# Download from service93scp -s YOUR_SERVICE@ssh.YOUR_REGION.render.com:/mount/path/file ./local-file9495# Upload to service96scp -s ./local-file YOUR_SERVICE@ssh.YOUR_REGION.render.com:/mount/path/file97```9899Requires SSH access enabled for the service.100101### Magic-Wormhole102103Available on all native runtimes (install manually on Docker):104105```bash106# On the service shell107wormhole send /mount/path/file108109# On your local machine110wormhole receive111```112113## Common Patterns114115| Pattern | Service type | Mount path | Notes |116|---------|-------------|------------|-------|117| WordPress / Ghost / CMS | Web Service | `/var/data` or `/app/content` | Media uploads, SQLite |118| Self-managed MySQL | Private Service | `/var/lib/mysql` | Use mysqldump for backups, not disk snapshots |119| File upload API | Web Service | `/opt/render/project/src/uploads` | Single instance constraint |120| Elasticsearch | Private Service | `/usr/share/elasticsearch/data` | Stateful search infrastructure |121122## Common Mistakes123124| Mistake | Fix |125|---------|-----|126| Expecting horizontal scaling with a disk | Not possible — disk services are single-instance only |127| Mounting at a disallowed path | Use a subdirectory (e.g. `/opt/render/project/src/uploads` not `/opt/render/project/src`) |128| Reading disk during build or pre-deploy | These run on separate compute — move logic to the start command |129| Restoring disk snapshot for a database | Use database-native backups instead |130| Starting with a large disk size | Start small — you can increase but never decrease |131132## References133134| Document | Contents |135|----------|----------|136| `references/sizing-and-snapshots.md` | Sizing guidance, snapshot lifecycle, restore procedures, cost patterns |137138## Related Skills139140- **render-web-services** — Deploy lifecycle, health checks (disk disables zero-downtime)141- **render-private-services** — Internal services with disks (Elasticsearch, MySQL)142- **render-blueprints** — `disk` field reference in `render.yaml`143- **render-postgres** — Managed database alternative (no disk management needed)