PostgreSQL on a VPS: how much RAM you actually need and which parameters to change immediately
Practical guide for Ubuntu 24.04: shared_buffers, work_mem, maintenance_work_mem and max_connections for VPSs with 2, 4 and 8 GB, plus final verification command.
UptimeMag editorial team · 13 October 2026 · 5 min read

When you install PostgreSQL on a VPS with apt install postgresql, you get a database configured to run anywhere, even on a machine with 512MB of RAM. The result: on a 4 or 8 GB VPS, the engine leaves most of the available memory on the table. This guide covers the parameters that matter, with starting values for 2, 4 and 8 GB of RAM.
Installation on Ubuntu 24.04
The system package is enough to get started:
sudo apt update
sudo apt install postgresql
For a specific version and dedicated updates, the PostgreSQL project provides a separate apt repository. As stated on the official download page for Ubuntu, to install PostgreSQL on Ubuntu you use the apt install postgresql command, and the Apt repository supports, among others, the noble distribution (24.04, LTS). To install a specific version from the PGDG repository:
sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
sudo apt install postgresql-18
The configuration file on Ubuntu is located at /etc/postgresql/<version>/main/postgresql.conf.
Why defaults don't work well on a dedicated VPS
The official PostgreSQL documentation is explicit about factory values. For shared_buffers: Sets the amount of memory the database server uses for shared memory buffers. The default is typically 128 megabytes (128MB), but might be less if your kernel settings will not support it. However, settings significantly higher than the minimum are usually needed for good performance.
For work_mem: Sets the base maximum amount of memory to be used by a query operation (such as a sort or hash table) before writing to temporary disk files. The default value is four megabytes (4MB).
For maintenance_work_mem: Specifies the maximum amount of memory to be used by maintenance operations, such as VACUUM, CREATE INDEX, and ALTER TABLE ADD FOREIGN KEY. It defaults to 64 megabytes (64MB).
For max_connections, the official connections page states: "The default is typically 100 connections, but might be less if your kernel settings will not support it".
The same documentation provides basic guidance on sizing shared_buffers: If you have a dedicated database server with 1GB or more of RAM, a reasonable starting value for shared_buffers is 25% of the memory in your system. And it adds an upper limit: beyond that threshold PostgreSQL continues to rely on the operating system cache, so it rarely makes sense to go above 40% of total RAM for shared_buffers, as explained in the same guide chapter (section 19.4.1 "Memory").
Starting values for 2, 4 and 8 GB of RAM
These values follow the logic of PGTune, the tool that generates starting configurations based on hardware: it's a web-based tool that generates recommended settings for PostgreSQL based on hardware and workload, producing a postgresql.conf ready with parameters like shared_buffers for data caching. Those who want to generate the complete file (including effective_cache_size, wal_buffers, max_wal_size) can do so on pgtune.leopard.in.ua by specifying RAM, number of CPUs and VPS storage type; here we report the four parameters that change almost always on the first day of operation, with the logic used to calculate them (25% of RAM for shared_buffers, remaining quota for work_mem based on estimated max_connections).
| VPS RAM | shared_buffers | work_mem | maintenance_work_mem | max_connections |
|---|---|---|---|---|
| 2 GB | 512MB | 4MB | 128MB | 50 |
| 4 GB | 1GB | 8MB | 256MB | 75 |
| 8 GB | 2GB | 16MB | 512MB | 100 |
Practical notes on these numbers:
shared_buffersstays at 25% of total RAM across all three profiles, in line with official guidance for dedicated servers with 1GB or more. On a shared VPS with other services running (nginx, redis, application), it's worth dropping to 15-20% to leave room for the rest of the stack.work_memis a value per operation, not per connection: a query with multiple concurrent sorts or hashes can multiply it. On VPSs with limited RAM it's best to stay low (4-8MB) and raise it only if repeated "temporary file" lines appear in the logs.maintenance_work_memaffects only VACUUM, CREATE INDEX and dump/restore: it can be set higher than work_mem without risk, because since only one of these operations can be executed at a time by a database session, and an installation normally doesn't have many of them running concurrently, it's safe to set this value significantly larger than work_mem.max_connectionslower than 100 is not a hard limit: with limited RAM it's better to keep it low and use a connection pooler (pgbouncer) in front of the database, rather than raising it and risking running out of memory when all connections are active at once.
How to apply the changes
Two equivalent approaches. The first, by editing the file:
sudo nano /etc/postgresql/18/main/postgresql.conf
and modifying the shared_buffers, work_mem, maintenance_work_mem, max_connections lines with your chosen values, then:
sudo systemctl restart postgresql
The second, from the SQL command line, with ALTER SYSTEM, useful because it doesn't require you to find the line in the file: ALTER SYSTEM is used for changing server configuration parameters across the entire database cluster. ALTER SYSTEM writes the given parameter setting to the postgresql.auto.conf file, which is read in addition to postgresql.conf.
sudo -u postgres psql -c "ALTER SYSTEM SET shared_buffers = '1GB';"
sudo -u postgres psql -c "ALTER SYSTEM SET work_mem = '8MB';"
sudo -u postgres psql -c "ALTER SYSTEM SET maintenance_work_mem = '256MB';"
sudo -u postgres psql -c "ALTER SYSTEM SET max_connections = 75;"
sudo systemctl restart postgresql
shared_buffers and max_connections are "static" parameters: they require a service restart, a reload is not enough. work_mem and maintenance_work_mem can also be applied with a simple reload (sudo systemctl reload postgresql or SELECT pg_reload_conf();), but after a series of changes it's still a good idea to restart to make sure everything is aligned.
Verifying that the changes have been applied
After restart, from psql:
sudo -u postgres psql -c "SHOW shared_buffers;"
sudo -u postgres psql -c "SHOW work_mem;"
sudo -u postgres psql -c "SHOW maintenance_work_mem;"
sudo -u postgres psql -c "SHOW max_connections;"
For a one-shot check with source values (file vs default vs session):
sudo -u postgres psql -c "SELECT name, setting, unit, source FROM pg_settings WHERE name IN ('shared_buffers','work_mem','maintenance_work_mem','max_connections');"
The source column should show configuration file (if modified in .conf) or remain consistent with postgresql.auto.conf if you used ALTER SYSTEM. If it still shows default, the change was not read: verify that you've restarted the correct service (systemctl status postgresql@18-main on multi-version installations) and that you don't have a second configuration file that overrides the first.
A word of caution about the numbers in this table
These values are a starting point, not a final configuration. They need to be verified with actual load: if repeated temporary file lines appear in PostgreSQL logs, raise work_mem; if top shows active swap after restart, shared_buffers is too high for the RAM actually free on the VPS (a VPS with control panel, PHP-FPM and Redis running has much less free RAM than a database-only server). For finer tuning, with effective_cache_size, wal_buffers and checkpoint_completion_target, the reference tool remains PGTune, to be used by entering the actual VPS data, not those of a dedicated server.
Written with the help of artificial intelligence and checked by the editors (EU AI Act, art. 50).