Concurrency is the number of operations or clients active at overlapping times. In PostgreSQL, raising it is not a free route to parallel work: each connection consumes resources, and excessive concurrent work can reduce throughput while sharply increasing latency. Size concurrency for the workload and host rather than treating a high connection limit as capacity. section 6.13 section 6.3
The tempting mistake is to set max_connections high enough for every client to connect directly. Many mostly idle sessions still impose computational overhead. Active sessions also compete for finite CPU and may contend on shared PostgreSQL objects through Lightweight Locks (LWLocks), so a server can appear busy without completing useful work quickly. section 6.13 section 6.3
Treat concurrency as a measured operating limit:
- Benchmark several client counts and compare both TPS and latency; a throughput plateau can conceal an overloaded server that is trading response time for concurrency. section 6.3
- Keep connection counts workload-specific. A stated empirical starting point is no more than four PostgreSQL connections per CPU core, not a universal rule. section 6.3
- Avoid idle connections where possible; when they cannot be avoided, use a connection pooler aware of PostgreSQL connection semantics, such as PgBouncer in Transaction Mode. section 6.13
- Find and resolve idle-in-transaction sessions and long-running queries. They can block other queries, delay applications, and postpone or block autovacuum. section 6.13
A 2,000-client benchmark hides overload
A pgbench run with 2,000 clients processed about 352 TPS at 5,535 ms average latency. Reducing clients raised TPS through 250 clients, but latency did not stabilize near 53–56 ms until 32 or 16 clients. The result is not “more clients is faster”: inspect latency alongside TPS to locate a sustainable concurrency level. section 6.3 section 6.3
Table 6.1 Test results showing TPS and latency with various numbers of clients
|
Number of clients
|
TPS
|
Latency average
|
|---|---|---|
|
2,000
|
352.1
|
5,535.267 ms
|
|
1,500
|
506.8
|
2,869.986 ms
|
|
1,000
|
586.1
|
1,694.616 ms
|
|
500
|
628.4
|
794.688 ms
|
|
250
|
635.7
|
392.554 ms
|
|
125
|
556.9
|
224.411 ms
|
|
63
|
613.0
|
102.758 ms
|
|
32
|
572.3
|
55.907 ms
|
|
16
|
301.8
|
53.009 ms
|
Compare the TPS plateau with the falling latency across client counts; the table makes the cost of excessive concurrency visible. section 6.3
Concurrency also affects maintenance safety. High transaction rates can outrun autovacuum’s work to prevent XID wraparound, while disabling or weakening autovacuum merely defers the cost into bloat, inaccurate statistics, and forced anti-wraparound work. Reduce avoidable ingestion through batching, reorganization, summarization, or skipping data unlikely to be reused. section 6.13






















