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.

Why shared memory runs outBig queryparallel workersPostgres allocatesin /dev/shmDocker default64 MB limitAllocation failsNo space leftThe error is about the container's shared memory size, not about disk space.
  1. Check the size inside the container: docker compose exec db df -h /dev/shm.
  2. Raise it in Compose: shm_size: 1gb on the database service.
  3. In Kubernetes, mount an emptyDir with medium: Memory at /dev/shm.
  4. With docker run, pass --shm-size=1g.
  5. If you cannot change it, limit parallelism: max_parallel_workers_per_gather = 0 for 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.

the one line that mattersservices:db:image: postgres:17shm_size: 1gbmem_limit: 4g121Replaces the 64 MB Docker default for /dev/shm.2Shared memory counts toward this limit.Recreate the container for the new size to applydjango-deployment.com
A restart keeps the old size; docker compose up -d recreates the container with the new one.

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.

where the 64 MB limit appliesDefault shmHow to raiseBare server or VMhalf of RAMnot neededDocker / Compose!64 MBshm_sizeKubernetes pod!64 MBMemory emptyDirManaged databaseprovider-managednot neededOnly containerized PostgreSQL hits this limitdjango-deployment.com
Moving to a managed database removes the setting from your responsibilities 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 segment while 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-size to 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

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.

Keep going