Keeping Data Alive on Railway: How to Use Persistent Volumes for Durable Local Storage
Railway’s default filesystem is transient, but you can attach durable local storage with persistent volumes. Learn how to create, mount, size, and test volumes for stateful workloads, plus the trade‑offs you need to watch out for.
03 May 2026, 23:45 UTC

The Problem: Ephemeral Filesystems
When you deploy a service on Railway, the container’s root filesystem is temporary. Any file written to /app or /tmp disappears when the instance is replaced during a redeploy, a scale‑up, or a provider‑level restart. For stateless services this is fine, but stateful workloads—databases, file uploads, caches—require a durable storage layer.
Why Persistent Volumes Matter
Railway offers Persistent Volumes as a first‑class feature. A volume is a block device that lives beyond the life cycle of any single container. Once attached to a service and mounted at a path like /data, the contents survive:
- Deploys – new code or configuration changes.
- Instance replacements – when Railway spins up a new container.
- Service restarts – triggered by health‑check failures or manual restarts.
Typical use cases include:
- Local database data directories (e.g.,
./var/lib/postgresql/data). - User uploads or media libraries.
- Application caches or temporary files that should persist across restarts.
Getting Started: Create & Attach a Volume
Below is a step‑by‑step example that demonstrates how to add a durable local storage area to a Railway service. The example assumes you have the Railway CLI installed and are logged in.
- Create a volume for uploads, 10 GB in size:
# Run in the terminal, in the root of your Railway project railway volume create uploads --size 10Replace
10with the desired size in GB. The command outputs the volume ID (e.g.,vol-123abc). - Attach the volume to a service named
apiand mount it at/data:# Attach the volume railway volume attach uploads api --mount-path /dataThis binds the volume to the
apiservice. Only one service can use a volume at a time; if you need shared access, consider an external object store. - Deploy the service so the mount is active:
# Deploy the updated configuration railway deployAfter the deploy completes, the container will have
/datamounted to the volume.
Confirming the Mount Inside the Container
You can verify the mount by opening an interactive shell in the running container:
# Get the service instance name
railway services
# SSH into the running instance
railway ssh api
# Inside the shell, list the mount
ls -l /data
You should see the volume’s mount point listed.
Sizing & Performance Considerations
Volume size is a simple integer in GB, but the underlying provider determines the actual performance characteristics. Railway’s plan tier dictates maximum volume size and IOPS. For example:
| Plan | Max Volume Size | Typical IOPS |
|---|---|---|
| Starter | 50 GB | 200 IOPS |
| Pro | 200 GB | 400 IOPS |
| Enterprise | 1 TB | 800 IOPS |
When choosing a size, consider both the peak data volume and the expected growth rate. Over‑provisioning wastes credits; under‑provisioning can lead to throttling.
Testing Persistence
To ensure the volume behaves as expected, perform a simple write‑and‑redeploy test:
- Write a test file inside the container:
# SSH into the service railway ssh api # Create a file in the mounted path echo "Hello, Railway!" > /data/hello.txt # Verify it exists cat /data/hello.txt - Trigger a redeploy (e.g., commit a trivial change or run
railway deploy):# Make a non‑functional change sed -i 's/placeholder/placeholder/' README.md railway deploy - After the deploy completes, **SSH back in** and confirm the file is still there:
# SSH again railway ssh api # Check the file cat /data/hello.txtIf the file is present, the volume survived the redeploy.
Limitations & Trade‑offs
- Single‑service attachment: A volume can only be attached to one service at a time. If you need multi‑replica access, you must use an external storage solution or implement application‑level sharding.
- No automatic replication: Volumes are not replicated across availability zones or regions. If your service fails in the region where the volume lives, the data is lost unless you have backup procedures.
- No built‑in backups: Railway does not snapshot volumes automatically. You must export or snapshot the data yourself (e.g., using
railway volume exportor a custom script). - Region‑bound: Moving a service to a different Railway region requires manual migration of the volume’s data.
Actionable Takeaways
- Use
railway volume createto provision durable storage for stateful workloads. - Attach the volume to one service and mount it at a clear, predictable path.
- Always test persistence by writing a file, redeploying, and verifying the file remains.
- Plan for backups and regional failover if your application requires high availability.
- Document the volume size and mount path in your project README so new team members understand the storage layout.
Persistent volumes give you the simplicity of local storage without the hassle of configuring external object stores. With careful sizing, testing, and awareness of the limitations, you can confidently run stateful services on Railway.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.