Skip to content
EL
Contents

Buffer cache, I/O and memory

Should this memory change ship?

DecisionAdvanced3 min read10 min hands-on#storage#operations

The idea in 30 seconds

Memory settings are tempting to raise because one slow query got faster. Before approving, multiply: work_mem times the sort and hash steps in a query, times the connections that can run at once, must still fit in the machine alongside shared buffers and the operating system cache. Prefer raising limits for the one job that needs them.

Helps to know first: How a table is stored on disk

On this page

The situation

A nightly finance report started spilling sorts to disk and now takes several minutes. The database server has 16 GB of RAM, max_connections is 200, and the application keeps about 100 connections open. An AI assistant opened a pull request.

Review taskRaise memory for the report

Pull request: “The finance report spills to disk. Give PostgreSQL more memory.”

# postgresql.conf
shared_buffers = 12GB      # was 4GB
work_mem = 1GB             # was 4MB

Would you approve it? Write the review you would leave.

Your call

How to decide

Prefer the narrowest scope: a setting for one transaction (SET LOCAL), one session, one role or one database before the whole server.

Do the multiplication for any work_mem change: value × sort and hash steps per query × connections that may run them at once. Compare with the memory left after shared buffers.

Leave room for the operating system cache. PostgreSQL depends on it; shared_buffers above about 40% of RAM rarely helps.

Measure the spill before fixing it. EXPLAIN (ANALYZE, BUFFERS) shows how much was spilled and how long it took; often the real cost is elsewhere.

Check yourself

  1. Why is work_mem = 1GB dangerous even if each report query only needs that much once?

    Show answer

    It is a per-operation limit applied to every connection. Any query with several sort or hash steps, in any of the 100 connections, may claim up to that much per step, and they can all run at the same time.

  2. How would you give only the report more sort memory?

    Show answer

    SET LOCAL work_mem inside the report’s transaction, SET work_mem in its session, or ALTER ROLE ... SET work_mem for the role it runs as.

  3. Why is shared_buffers at 75% of RAM likely to make things worse rather than better?

    Show answer

    PostgreSQL relies on the operating system’s page cache too. Giving shared buffers most of the RAM squeezes that cache, every connection’s own memory and the operating system, which can cause swapping.

Finished reading?

Saved in this browser only.

Sources

Where each claim on this page comes from.

  1. 1.
    PostgreSQL documentation: 19.4 Resource Consumption
    Primary· §19.4.1 Memory

    work_mem applies per sort or hash operation and total use can be many times its value; shared_buffers of 25% of RAM is a reasonable start and over 40% is unlikely to help; maintenance_work_mem is used by VACUUM and CREATE INDEX.

  2. 2.
    PostgreSQL documentation: SET
    Primary· Parameters: LOCAL

    SET LOCAL takes effect only for the current transaction.

  3. 3.
    PostgreSQL documentation: ALTER ROLE
    Primary· Description

    ALTER ROLE ... SET changes a role's session default for a setting.

  4. 4.
    PostgreSQL documentation: 18.4 Managing Kernel Resources
    Primary· §18.4.4 Linux Memory Overcommit

    When memory runs out on Linux, the kernel may terminate the PostgreSQL postmaster; memory-related settings such as shared_buffers, work_mem and hash_mem_multiplier can contribute.

Go further

What to read next, and why it is worth the time.

  1. 1.
    PostgreSQL documentation: 19.4 Resource Consumption
    Primary· §19.4.1

    Every memory setting with its default and the caveats that go with it.

Applies to PostgreSQL 18. Draft: not yet fact-checked end to end.