Fix PostgreSQL "Could Not Resize Shared Memory Segment" in Docker
Fix the PostgreSQL error could not resize shared memory segment No space left on device in Docker and Kubernetes: raise /dev/shm with shm_size or a memory-backed emptyDir, and tune parallel query and work_mem for Django workloads.
Problem statement
A report page or an admin list with filters fails, while simple pages work fine:
django.db.utils.OperationalError: could not resize shared memory segment
"/PostgreSQL.1234567" to 8388608 bytes: No space left on device
The disk is not full. PostgreSQL uses POSIX shared memory in /dev/shm for parallel query workers and some hash operations. Docker gives every container a /dev/shm of only 64 MB by default. When a query uses parallel workers or a large hash join, PostgreSQL tries to allocate more than that and fails.
- Check the size inside the container:
docker compose exec db df -h /dev/shm. - Raise it in Compose:
shm_size: 1gbon the database service. - In Kubernetes, mount an
emptyDirwithmedium: Memoryat/dev/shm. - With
docker run, pass--shm-size=1g. - If you cannot change it, limit parallelism:
max_parallel_workers_per_gather = 0for that database.
Step-by-step solution
1. Confirm the limit
docker compose exec db df -h /dev/shm
Size 64M confirms the Docker default. On the host, the same database would have half the RAM available in /dev/shm, which is why the query works elsewhere.
2. Raise shm_size in Docker Compose
services:
db:
image: postgres:17
shm_size: 1gb
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/pg_password
volumes:
- pgdata:/var/lib/postgresql/data
Recreate the container (docker compose up -d db); a restart alone does not change the size. Shared memory counts against the container's memory limit, so make sure mem_limit or deploy.resources.limits.memory leaves room for it.
3. Fix it in Kubernetes
Pods have no shm_size field. Mount a memory-backed volume:
spec:
containers:
- name: postgres
image: postgres:17
volumeMounts:
- name: dshm
mountPath: /dev/shm
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 1Gi
Operators such as CloudNativePG and Crunchy PGO handle this for you; check their configuration before adding your own mount.
4. Or reduce what queries need
If you cannot change the container, reduce parallel query, which is the main consumer:
ALTER DATABASE appdb SET max_parallel_workers_per_gather = 0;
New connections pick it up. This trades the error for slower large scans. A middle ground is 2 with a larger shm.
5. Find the query
Turn on log_min_error_statement = error (the default) and read the database log to see which statement failed. Typical culprits in Django apps are admin changelists with date_hierarchy on big tables, count() on unindexed filters, and reports that aggregate millions of rows. Adding an index often removes the need for a parallel scan entirely.
Explanation
Since PostgreSQL 10, parallel query workers exchange data through dynamic shared memory segments, created by default as POSIX shared memory (dynamic_shared_memory_type = posix), which lives in /dev/shm. Docker mounts a small tmpfs there for isolation. When the planner chooses a parallel plan, each worker and the leader allocate segments sized by the data being exchanged and by work_mem. A few concurrent parallel queries easily exceed 64 MB.
Edge cases / notes
- Bus error instead. Some versions report
could not resize shared memory segmentwhile others crash a backend with a bus error (SIGBUS). Both have the same fix. - Test databases. CI runs with the default shm can fail on tests that run large aggregations. Add
--shm-sizeto the CI service container too. - Memory limits. If the container hits its memory limit after raising shm, the OOM killer stops PostgreSQL. Size limits for shared buffers, shm, and backends together.
Next steps
- Review database container settings in Deploy Django With Docker Compose in Production.
- Size memory settings with Tune PostgreSQL Settings for Django.
- If the disk really is full, see Fix Django Server Disk Full.
FAQ
Is my disk full?
No. "No space left on device" here refers to the /dev/shm tmpfs inside the container, not your data volume.
How big should shm_size be?
1 GB is a common, safe value for small and medium databases. It is a limit, not a reservation, so it uses memory only when queries need it.
Why does the query work on my laptop?
PostgreSQL installed directly on the laptop has a much larger /dev/shm. Only the container has the 64 MB limit.
Will disabling parallel query hurt performance?
Large scans become slower, but typical Django page queries rarely use parallel plans. Prefer raising shm and keep parallelism if you can.