Postgres Configuration Tuning

When you created your Fly Postgres cluster, Postgres configuration parameters were set to reasonable defaults for your VM resources.

flyctl exposes some of these parameters so you can tune them to your application’s needs, or to match any VM scaling you do.

Before you start tuning, it’s important to understand the tradeoffs that you’re making. Choose values for these parameters with the guidance of the Postgres docs.

View current configuration

View your cluster’s current configurable settings with fly postgres config show:

fly postgres config show --app <pg-app-name>
NAME                        VALUE   UNIT    DESCRIPTION                                                                                 PENDING RESTART
log-min-duration-statement  -1      ms      Sets the minimum execution time above which all statements will be logged. (-1, 2147483647) false
log-statement               none            Sets the type of statements logged. [none, ddl, mod, all]                                   false
max-connections             300             Sets the maximum number of concurrent connections. (1, 262143)                              false
shared-buffers              8192    8kB     Sets the number of shared memory buffers used by the server. (16, 1073741823)               false
shared-preload-libraries                    Lists shared libraries to preload into server.                                              false
wal-level                   replica         Sets the level of information written to the WAL. [minimal, replica, logical]               false

(The shared-buffers value is indeed in units of 8kB, so a value of 8192 corresponds to 64MB of RAM that Postgres will use for shared buffers.)

Update configuration settings

To demo how this works we’ll update the max-connections setting from 300 to 500 using fly postgres config update.

fly postgres config update --max-connections 500 --app <pg-app-name>
NAME            VALUE   TARGET VALUE    RESTART REQUIRED
max-connections 300     500             true

? Are you sure you want to apply these changes? Yes
Acquired lease f912530da158 on machine: 4d89649b460987
Performing update...
Update complete!
Please note that some of your changes will require a cluster restart before they will be applied.
To review the state of your changes, run: `fly postgres config show`
? Restart cluster now? Yes
Identifying cluster role(s)
  Machine e286030f792186: replica
  Machine e784977a42e983: replica
  Machine 4d89649b460987: leader
Restarting machine e286030f792186
  Waiting for e286030f792186 to become healthy (started, 3/3)
Machine e286030f792186 restarted successfully!
Restarting machine e784977a42e983
  Waiting for e784977a42e983 to become healthy (started, 3/3)
Machine e784977a42e983 restarted successfully!
Attempting to failover 4d89649b460987
Restarting machine 4d89649b460987
  Waiting for 4d89649b460987 to become healthy (started, 3/3)
Machine 4d89649b460987 restarted successfully!
Postgres cluster has been successfully restarted!

Each VM belonging to your Postgres app will be restarted to apply the changes. If you have a replica for high availability, this is updated and restarted first, and it becomes leader before the old leader gets updated.

We can take one last look at our config show and see that our max-connections value has now officially been applied!

fly postgres config show --app <pg-app-name>
NAME                        VALUE   UNIT    DESCRIPTION                                                                                 PENDING RESTART
log-min-duration-statement  -1      ms      Sets the minimum execution time above which all statements will be logged. (-1, 2147483647) false
log-statement               none            Sets the type of statements logged. [none, ddl, mod, all]                                   false
max-connections             500             Sets the maximum number of concurrent connections. (1, 262143)                              false
shared-buffers              8192    8kB     Sets the number of shared memory buffers used by the server. (16, 1073741823)               false
shared-preload-libraries                    Lists shared libraries to preload into server.                                              false
wal-level                   replica         Sets the level of information written to the WAL. [minimal, replica, logical]               false

Gotchas

If you mismatch Postgres parameters and VM RAM, you may end up with an unhealthy cluster and errors like this in your logs (these are from an older Stolon-managed cluster):

[info]keeper   | 2022-11-13 16:46:20.260 UTC [717] FATAL:  could not map anonymous shared memory: Cannot allocate memory
[info]keeper   | 2022-11-13 16:46:20.260 UTC [717] HINT:  This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space, or huge pages. To reduce the request size (currently 1135091712 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

If you’re scaling your instances up, do that before adjusting the Postgres config to match. If you’re scaling down, adjust the cluster’s Postgres parameters to match the reduced resources before scaling the VM.