Handling State in Scalingo: Managing Ephemeral Filesystems
Learn why files disappear on Scalingo and how to transition from a local filesystem to a stateless architecture using object storage and managed databases.
21 Jan 2026, 07:48 UTC

The 'Vanishing File' Problem
A common point of friction for developers moving from traditional VPS (Virtual Private Server) environments to Scalingo is the discovery that files written to the local disk disappear. You might upload a user profile picture or generate a PDF report, only to find those files missing after a new deployment or a routine container restart. This happens because Scalingo uses an ephemeral filesystem.
The takeaway is simple: your application must be stateless. Any data that needs to persist across restarts or be shared between multiple containers must live in an external service, not on the local disk.
How the Container Model Works
Scalingo utilizes a container-orchestration layer that abstracts the underlying infrastructure. When you deploy via git push, the platform uses Buildpacks—scripts that detect your language runtime—to compile your code and dependencies into a portable "slug" (a compressed snapshot of your app). This slug is then deployed into one or more containers.
To ensure high availability and seamless horizontal scaling, these containers are designed to be disposable. When you scale up to handle more traffic, Scalingo spins up identical copies of your slug. Because these containers do not share a local disk, a file written to Container A is invisible to Container B. Furthermore, when a container is recycled during a deployment, the entire local filesystem is wiped and reset to the original state of the slug.
Architecting for Persistence
To move away from local storage, you should implement one of the following patterns based on the data type:
- Structured Data: Use a managed database (PostgreSQL, MySQL, etc.). Scalingo provides integrated add-ons for these services.
- Unstructured Files: Use object storage services like AWS S3, Google Cloud Storage, or Azure Blob Storage.
- Session Data: Use an in-memory store like Redis to maintain user sessions across multiple container instances.
Example: Shifting from Local to Object Storage
Consider a Node.js application using the multer middleware for file uploads. A typical "naive" implementation saves files to a /uploads folder on the local disk. To make this work on Scalingo, you must swap the storage engine.
// Local Storage (Will fail on Scalingo restarts)
const storage = multer.diskStorage({
destination: './uploads/',
filename: (req, file, cb) => { cb(null, file.originalname) }
});
// Cloud Storage (The correct approach)
// Use a library like 'multer-s3' to stream uploads directly to a bucket
const { S3Client } = require("@aws-sdk/client-s3");
const multerS3 = require("multer-s3");
const s3 = new S3Client({ region: "eu-west-3" });
const upload = multer({
storage: multerS3({
s3: s3,
bucket: process.env.S3_BUCKET_NAME,
key: function (req, file, cb) {
cb(null, Date.now().toString() + '-' + file.originalname)
}
})
});In this configuration, the application relies on environment variables (S3_BUCKET_NAME) to identify the destination, adhering to the Twelve-Factor App methodology. This ensures that the container remains a stateless execution engine.
Trade-offs and Limitations
While statelessness enables effortless horizontal scaling, it introduces a few engineering trade-offs:
- Latency: Fetching a file from S3 is slower than reading from a local SSD. For high-performance needs, implement a caching layer or use a Content Delivery Network (CDN).
- Complexity: You now have to manage external API keys and handle network timeouts when communicating with your storage provider.
- Cold Starts: While not related to storage, remember that deploying a new slug involves initializing a new container, which can cause a brief "cold start" latency spike.
Verifying Your Statelessness
To confirm your app is truly stateless and won't lose critical data in production, perform this diagnostic check:
- Run a command or trigger an action in your app that writes a file to the local disk.
- Verify the file exists via a temporary debug endpoint or log.
- Restart the container using the Scalingo dashboard or CLI.
- Attempt to access the file again. If it is gone, your app is correctly behaving as a stateless container; if you relied on that file, you must migrate it to external storage.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.