Guides / OSError: [Errno 28] No space left on device (Django)
OSError: [Errno 28] No space left on device (Django)
Requests start failing with OSError: [Errno 28] No space left on device, or Postgres reports could not write to file ... No space left on device. The disk is full. In a Django app the culprits are almost always the same few: logs, temporary upload files, sessions or cache written to disk, and old Docker data.
What it means
Something filled the filesystem (or used up its inodes, the file count limit) that Django, Postgres or Python writes to. The first thing to break is usually whatever writes at that moment: a log line, an upload, a session or a migration.
Why it happens
- Log files grow forever. Application logs, gunicorn and nginx logs, or Docker's JSON logs without rotation.
- Docker data piles up. Old images, stopped containers and build cache from every deploy.
- Temporary upload files. Large uploads are spooled to
/tmp(FILE_UPLOAD_TEMP_DIR) and are not cleaned up when a request is aborted. - File-based sessions or cache (
django.contrib.sessions.backends.file,FileBasedCache) that never expire their files, or a database-backed session table never cleaned. - The database itself: a SQLite file, or Postgres WAL and tables on a small volume.
- A small root disk, such as 8 GB on a fresh cloud instance.
The fix
Find what is using the space before deleting anything:
df -h # which filesystem is full?
df -i # or is it out of inodes?
sudo du -xh / --max-depth=2 2>/dev/null | sort -h | tail -20
docker system df # if you use Docker
Then clean up the cause:
docker image prune -a --filter "until=168h" # images unused for a week
docker builder prune
sudo journalctl --vacuum-size=200M
python manage.py clearsessions # remove expired database sessions
For log files, rotate them (logrotate for nginx and gunicorn files) or stop writing them to disk. In Django, log to the console and let the platform collect the output:
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {"console": {"class": "logging.StreamHandler"}},
"root": {"handlers": ["console"], "level": "INFO"},
}
If you need files, use logging.handlers.RotatingFileHandler with maxBytes and backupCount. For Docker's own logs, set a size cap in /etc/docker/daemon.json:
{"log-driver": "json-file", "log-opts": {"max-size": "10m", "max-file": "3"}}
Making it stick in production
- Alert at 80 percent disk usage, not at 100.
- Keep state out of the app's filesystem: sessions in the database or cache, files in object storage, logs in a log service.
- Schedule
clearsessionsdaily, and prune Docker images as part of the deploy. - Give the volume room for the database to grow, and monitor its size.
Or skip it
On Django Cloud your app's disk is reset on every deploy, so state belongs in Postgres, and your logs live in the dashboard, searchable and kept for 30 days, and not in files that grow on the server.
pip install djangocloud-cli
djangocloud deploy
Free plans are available for students, AWS Activate startups, open-source, non-profit and research projects. See how Django Cloud compares with other ways to host Django.
Django is a registered trademark of the Django Software Foundation. Django Cloud is not affiliated with or endorsed by it. Found a mistake in this guide? Tell us and we will fix it.