doc/administration/postgresql/tune.md
{{< details >}}
{{< /details >}}
You should tune PostgreSQL when:
The following settings are required for externally managed PostgreSQL instances.
| Tunable setting | Required value | More information |
|---|---|---|
work_mem | minimum 8 MB | This value is the Linux package default. In large deployments, if queries create temporary files, you should increase this setting. |
maintenance_work_mem | minimum 64 MB | You require more for larger database servers. |
max_connections | minimum 400 | Calculate based on your GitLab components. See Plan your database connections for detailed guidance. |
shared_buffers | minimum 2 GB | You require more for larger database servers. The Linux package default is set to 25% of server RAM. |
statement_timeout | 15000 to 60000 | A statement timeout prevents runaway issues with locks and the database rejecting new clients. You should use values between 15 and 60 seconds (15000 to 60000 milliseconds), where one minute matches the Puma rack timeout setting. |
hot_standby_feedback | on | For configurations with multiple nodes and database load balancing configured, ensure that all replica nodes have hot_standby_feedback enabled to prevent lag buildup. |
You can configure some PostgreSQL settings for the specific database, rather than for all databases on the server.
statement_timeout on a specific database or user, but not as a database flag.
For example: ALTER DATABASE gitlab SET statement_timeout = '60s';[!note] GitLab versions 16.0 and later use two sets of database connections for the
mainandcitables. This doubles connection usage, even when the same PostgreSQL database serves both sets of tables.
GitLab uses database connections from multiple components. Proper connection planning prevents database connection exhaustion and performance issues.
Each GitLab component uses database connections based on its configuration. Sidekiq and Puma establish a pool of connections to PostgreSQL at initialization. The number of connections in the pool can increase later if there are connection spikes or temporary increases in demand:
DB_POOL_HEADROOM.Puma connections = puma['worker_processes'] × (puma['max_threads'] + DB_POOL_HEADROOM)
By default:
puma['worker_processes'] is based on CPU core count.puma['max_threads'] is 4.DB_POOL_HEADROOM is 10.Per-worker calculation: Each Puma worker uses 4 threads + 10 headroom, for a total of 14 connections.
Default calculation, assuming 8 vCPU: 8 workers × 14 connections per worker, for a total of 112 Puma connections.
Sidekiq connections = Number of Sidekiq processes × (sidekiq['concurrency'] + 1 + DB_POOL_HEADROOM)
By default:
1.sidekiq['concurrency'] is 20.DB_POOL_HEADROOM is 10.Default calculation: 1 Sidekiq process × (20 concurrency + 1 + 10 headroom), for a total of 31 total Sidekiq connections.
The Geo Log Cursor daemon runs on all GitLab Rails nodes in a secondary site.
Geo log cursor connections = 1 + DB_POOL_HEADROOM
Default calculation: 1 + 10 headroom, for a total of 11 Geo connections.
For single node installations:
Total connections = 2 × (Puma + Sidekiq + Geo)
For multi-node installations, multiply by the number of nodes running each component:
Total connections = 2 × ((Puma × Rails nodes) + (Sidekiq × Sidekiq nodes) + (Geo × secondary Rails nodes))
Multiplying by 2 accounts for the dual database connections in GitLab 16.0 and later.
For Geo installations:
Geo = 0. Geo Log Cursor doesn't run on primary sites.max_connections to the same value on both the primary PostgreSQL database and all replica databases,
using the highest connection requirement across all Geo sites.This example is based on the GitLab reference architecture for 20 RPS (requests per second) or 1000 users:
| Component | Nodes | Configuration | Connections per component | Component total, dual database |
|---|---|---|---|---|
| Puma | 1 | 8 workers, 4 threads each | 14 per worker | 224 |
| Sidekiq | 1 | 1 process, 20 concurrency | 31 per process | 62 |
| Total | 286 |
This example is based on the GitLab reference architecture for 40 RPS (requests per second) or 2000 users:
| Component | Nodes | Configuration | Connections per component | Component total, dual database |
|---|---|---|---|---|
| Puma | 2 | 8 workers per node, 4 threads each | 14 per worker | 448 |
| Sidekiq | 1 | 4 processes, 20 concurrency each | 31 per process | 248 |
| Total | 696 |
This example is based on the GitLab reference architecture for 20 RPS (requests per second) or 1000 users.
| Component per Geo site | Nodes | Configuration | Connections per component | Component total, dual database |
|---|---|---|---|---|
| Puma | 1 | 8 workers, 4 threads each | 14 per worker | 224 |
| Sidekiq | 1 | 1 process, 20 concurrency | 31 per process | 62 |
| Geo Log Cursor (secondary sites only) | 1 | 1 process | 11 per process | 22 |
| Total | 308 |
This example is based on the GitLab reference architecture for 40 RPS (requests per second) or 2000 users:
| Component per Geo site | Nodes | Configuration | Connections per component | Component total, dual database |
|---|---|---|---|---|
| Puma | 2 | 8 workers per node, 4 threads each | 14 per worker | 448 |
| Sidekiq | 1 | 4 processes, 20 concurrency each | 31 per process | 248 |
| Geo Log Cursor (secondary sites only) | 2 | 1 process per Rails node | 11 per process | 44 |
| Total | 740 |