PRODSoeverein Europees BaaS-platformOpen Dashboard →

Prestaties · 9 min gelezen

Postgres max_connecties zonder pooler

Affane Daylami · Fondateur · 6 juni 2026

Terug naar blog

Zonder te poolen voor uw server, zou max_connections elke open clientverbinding tegelijkertijd moeten dekken, niet het aantal verzoeken dat Postgres efficiënt parallel kan verwerken. Het verwarren van deze twee getallen is de meest voorkomende oorzaak van verkeerd ingestelde max_connections: te laag om de belasting te absorberen, of te hoog voor het daadwerkelijk beschikbare geheugen.

Deze Engelse tekst is automatisch gegenereerd op basis van het Franse origineel en is nog niet beoordeeld.
Deze pagina is automatisch vertaald. De Engelse versie is gezaghebbend.

Dit artikel geeft de formule die is gepubliceerd door de PostgreSQL-wiki om de ideale gelijktijdigheid van uw hardware te berekenen (de meest geciteerde formule voor de grootte van de verbindingspool in het ecosysteem), legt uit waarom elke verbinding meer kost dan een applicatiethread en beschrijft vervolgens de procedure voor het instellen van max_connections zonder te raden. Onze benchmarkmethodologie documenteert het meetprotocol dat wordt gebruikt voor eventuele prestatieclaims op deze blog.

De essentie

  • Zonder pooling zouden max_connections alle gelijktijdige clientverbindingen moeten dekken, niet alleen de verbindingen die Postgres efficiënt parallel kan verwerken.
  • PostgreSQL-wiki-referentieformule: ideale actieve gelijktijdigheid = (fysieke kernen × 2) + efficiënte schijven. Een uitgangspunt dat gevalideerd moet worden door meting, geen harde grens.
  • max_connections is een contextparameter postmaster: het wijzigen ervan vereist een volledige herstart van de server, niet eenvoudigweg opnieuw laden.
  • Elke Postgres-verbinding is een afzonderlijk systeemproces en geen lichtgewicht draad: dit maakt de overhead reëel zodra het aantal verbindingen stijgt.
  • Geverifieerd in de code: op zijn speciale Postgres-clusters varieert Aurabase max_connections van 50 (gratis laag) tot 400 (ondernemingslaag), afhankelijk van de grootte van het cluster.
#
Diagnose

Waarom een Postgres-verbinding meer kost dan een applicatiethread

Postgres gebruikt geen lichtgewicht threadpool voor zijn verbindingen. Elke clientverbinding activeert een volwaardig systeemproces.

Het postmaster-proces maakt voor elke verbindingspoging een nieuwe (“fork”), bestemd voor deze enkele sessie totdat deze wordt gesloten. De officiële projectdocumentatie beschrijft precies dit mechanisme in het hoofdstuk over architecturale grondbeginselen (postgresql.org/docs/current/connect-estab.html, sectie “Verbindingssemantiek”, geraadpleegd op 24 augustus 2026).

Deze keuze heeft een echt voordeel: een crash op één verbinding heeft geen invloed op de andere, omdat elk proces geïsoleerd is van de rest van de server. Er zijn ook directe kosten aan verbonden: elke extra verbinding voegt een heel OS-proces toe aan de planning, met zijn eigen geheugenruimte en zijn eigen context-switching-overhead voor de kernel.

Wat verandert er in de praktijk

Een applicatie die 500 directe verbindingen met Postgres opent zonder te poolen, dwingt de server om 500 gelijktijdige systeemprocessen te beheren, zelfs als de overgrote meerderheid daarvan inactief blijft tussen twee verzoeken.

#
Geheugenkosten

Wat een verbinding feitelijk verbruikt: gedeeld geheugen en work_mem

Er zijn twee verschillende mechanismen die van invloed zijn op het geheugen, en het verwarren ervan leidt bijna altijd tot een verkeerde diagnose.

De eerste staat vast. Bij het opstarten reserveert Postgres gedeelde geheugenstructuren (sloten, procestabel) op basis van de waarde van max_connections, ongeacht of deze verbindingen vervolgens wel of niet worden geopend. De officiële documentatie voor de instelling wijst er expliciet op: het verhogen ervan kan meer gedeeld systeemgeheugen vereisen dan de standaardconfiguratie van uw besturingssysteem toestaat (postgresql.org/docs/current/runtime-config-connection.html, geraadpleegd op 24 augustus 2026).

De tweede is variabel en veel gevaarlijker op schaal: work_mem wordt niet één keer per verbinding toegewezen, maar één keer per sorteer- of hashbewerking in het queryplan. De officiële documentatie is expliciet op dit punt: een complexe query kan verschillende van deze bewerkingen parallel starten, en verschillende sessies kunnen hetzelfde tegelijkertijd doen, zodat het werkelijk gebruikte geheugen meerdere malen de moeite waard kan zijn work_mem (postgresql.org/docs/current/runtime-config-resource.html, geraadpleegd op 24 augustus 2026).

Het ergste geval om te onthouden

Het zijn niet alleen max_connections × work_mem die het geheugen van een server bedreigen. Het is max_connections × work_mem × aantal gelijktijdige bewerkingen per query. Het is dit product dat een server verklaart die verwisselt, of die geen geheugen meer heeft na een toename van het aantal max_connections dat als onschadelijk wordt beschouwd.

#
Formule

De formule voor de grootte van de PostgreSQL-wiki

De officiële PostgreSQL-projectwiki documenteert een benchmarkformule voor het berekenen van hoeveel actieve -verbindingen uw hardware efficiënt parallel kan verwerken, niet hoeveel verbindingen er in totaal geopend zijn (wiki.postgresql.org/wiki/Number_Of_Database_Connections, geraadpleegd op 24 augustus 2026).

De formule

ideale actieve gelijktijdigheid = (fysieke kernen × 2) + efficiënte schijven. Het aantal cores is exclusief hyperthreading. Het aantal effectieve schijven blijft dichtbij 1 op moderne SSD-opslag, waar het idee van een afzonderlijke fysieke schijf (“spindel”) veel van zijn oorspronkelijke betekenis verliest.

Op een server met 8 fysieke cores en SSD-opslag geeft de formule (8 × 2) + 1 = 17 actieve verbindingen voordat de doorvoer begint af te nemen. Dit cijfer is vaak verrassend: het lijkt klein vergeleken met de honderden verbindingen die een applicatie in de praktijk opent. Dit is precies het onderwerp van de volgende paragraaf.

Het getal dat door de formule wordt berekend, meet de gelijktijdigheid die de CPU en schijf kunnen absorberen, niet het aantal clientverbindingen dat uw toepassing moet openen. Een vloot van 20 applicatieprocessen, elk met een eigen pool van 10 verbindingen, opent 200 gelijktijdige verbindingen met Postgres, zelfs als er op een bepaald moment slechts 17 daarvan actief werken. Zonder een pooler moeten max_connections de 200 dekken, niet de 17. Het is deze kloof die de meeste architecturen ertoe aanzet een pooler toe te voegen in transactiemodus, zelfs als dit betekent dat ze moeten kiezen welke (zie onze vergelijking PgBouncer, Supavisor en PgCat).

#
Procedure

Hoe max_connections te veranderen (en waarom opnieuw opstarten vereist is)

max_connections is niet hot-swap. Dit is een contextparameter postmaster: Postgres leest deze één keer bij het opstarten, om het gedeelde geheugen te vergroten. Het opnieuw laden van de configuratie (pg_reload_conf() of SIGHUP) is niet voldoende; u moet de server opnieuw opstarten.

Controleer eerst de huidige waarde en de context ervan, om te bevestigen dat een herstart noodzakelijk is:

psqlsql
SHOW max_connections;

SELECT name, setting, context
FROM pg_settings
WHERE name = 'max_connections';

-- context='postmaster' bevestigt dat opnieuw opstarten vereist is

Pas vervolgens de nieuwe waarde toe en start vervolgens opnieuw:

psqlsql
ALTER SYSTEM SET max_connections = '300';

-- Geschreven in postgresql.auto.conf.
-- Geen effect totdat Postgres opnieuw is opgestart.
terminalbash
# Met systemd
sudo systemctl restart postgresql

# Zonder systemd, direct met pg_ctl
pg_ctl restart -D $PGDATA -m fast
Een marge die velen vergeten

max_connections bevat standaard superuser_reserved_connections (standaard 3): deze verbindingen zijn gereserveerd voor een superuser in geval van verzadiging, ze zijn nooit beschikbaar voor uw toepassing, zelfs als de globale teller nog niet is bereikt.

#
Code ingecheckt

Hoe Aurabase max_connections budgetteert op zijn Postgres-clusters

Het dimensioneren van max_connections is niet alleen een theoretische oefening. Hier ziet u hoe Aurabase het budgetteert op de beheerde Postgres-clusters:

100
POSTGRES STANDAARD
max_connections vóór elke afstemming
50→400
SPECIFIEKE AURABASE LAGERS
gratis voor ondernemingen, per CNPG-cluster
3
SUPERGEBRUIKER GERESERVEERD
superuser_reserved_connections, Postgres-standaard

Toegewijde clusters: één Postgres-cluster per project

Op dit niveau (zie onze vergelijking dedicated versus gedeelde basis), ontvangt elk project zijn eigen CloudNativePG-cluster en zijn eigen max_connections budget, afgestemd op de grootte van de instantie:

gratis (speciaal)max_verbindingen 501 exemplaar · 500m vCPU · 512Mi
pro (standaard)max_verbindingen 2002 instanties · 1 vCPU · 2Gi
teammax_verbindingen 3003 instanties · 2 vCPU · 3Gi
zakenmax_verbindingen 4003 instanties · 2 vCPU · 4Gi

Gedeelde clusters: meerdere projecten van een organisatie, een gedeeld budget

Op dit tweede pad zijn alle projecten van dezelfde organisatie verbonden via een CNPG-pooler (PgBouncer, transaction-modus) voor een gedeelde primaire:

gratismax_verbindingen 50max_client_conn 100max_user_connections 20
promax_verbindingen 100max_client_conn 200max_user_connections 60
teammax_verbindingen 200max_client_conn 400max_user_connections 150

Alle projecten in een organisatie zijn met elkaar verbonden via een gedeelde applicatierol. max_user_connections alleen al beperkt daarom het totale aantal serververbindingen dat deze rol in het hele cluster kan openen: dit is de echte cluster-globale beveiliging, niet max_client_conn, die alleen clientverbindingen met de pooler zelf beperkt.

Deze pooler bedient echter alleen SDK-applicatieverkeer. PostgREST blijft op zijn beurt rechtstreeks verbonden met de primaire (-rwservice): poolen in de transactiemodus zou het herlaadmechanisme van het schema verbreken, dat luistert naar een speciaal LISTEN kanaal met de naam pgrst. De eigen verbindingen (2 per replica op het gedeelde niveau, 10 per replica op het speciale niveau) tellen daarom direct mee in het max_connections budget van de primaire, buiten welke pooler dan ook, precies het soort “vergeten” verbinding dat stap 1 van de onderstaande procedure moet omvatten.

Cijfers die momenteel worden gekalibreerd, als zodanig aangenomen

De code documenteert deze gedeelde poolerbudgetten expliciet als startwaarden die in reële omstandigheden moeten worden gekalibreerd, door pg_stat_activity onder belasting te meten, en niet als vaste cijfers uit een gepubliceerde benchmark. Dit is dezelfde discipline als beschreven in onze benchmarkmethodologie: meten voordat je bijstelt, niet raden en dan hopen. Deze clusters draaien op PostgreSQL 16, een keuze die is gedocumenteerd in onze Postgres 16 versus 17 versus 18vergelijking.

#
Methode

De procedure in 5 stappen om max_connections op maat te maken zonder pooling

Deze procedure is niet afhankelijk van een bepaald hulpmiddel: het is van toepassing op elke Postgres-server, beheerd of zelfgehost.

  1. Tel uw daadwerkelijke clientverbindingen. Aantal applicatieprocessen vermenigvuldigd met de grootte van hun interne pool, plus beheertools, replicatie en monitoring. Het is dit getal, en niet de formule, dat de max_connections-vloer bepaalt.
  2. Bereken de ideale gelijktijdigheid van uw hardware met de formule uit de PostgreSQL-wiki: (fysieke kernen × 2) + efficiënte schijven. Dit cijfer geeft aan hoeveel van deze verbindingen feitelijk parallel kunnen werken zonder de doorvoer te verminderen.
  3. Stel max_connections in boven de daadwerkelijke behoefte voor stap 1, met marge voor superuser_reserved_connections en voor eventuele beheerderstools die hun eigen verbindingen buiten de applicatie openen.
  4. Pas de wijziging toe met ALTER SYSTEM SET en start vervolgens de server opnieuw op. Dit is een postmasterparameter: eenvoudig herladen is niet voldoende, zoals hierboven beschreven.
  5. Controleer pg_stat_activiteit in de loop van de tijd. Als het aantal inactieve verbindingen het aantal actieve verbindingen aanzienlijk overschrijdt, is dit geen max_connections-probleem: het is het signaal dat u een pooler vóór de server nodig heeft, niet een hoger aantal.

Het monitoringverzoek uit stap 5, direct bruikbaar:

psqlsql
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state
ORDER BY count(*) DESC;
#
Waarschuwingssignaal

Wanneer de formule niet langer genoeg is: de signalen dat je een pooler nodig hebt

Drie signalen keren systematisch terug wanneer max_connections alleen niet langer voldoende is, wat de waarde ervan ook is.

  1. De FATAL: sorry, too many clients already-fout verschijnt tijdens piekbelasting, terwijl de meerderheid van de verbindingen die door pg_stat_activity worden weergegeven zich in de inactieve status bevinden.
  2. De applicatie draait in een serverloze omgeving of met tijdelijke werkers (edge-functies, korte taken), die verbindingen veel sneller openen en sluiten dan waarvoor het proces-per-verbinding-model van Postgres was ontworpen.
  3. De bovenstaande formule en procedure zijn al toegepast, en de werkelijke behoefte aan clientverbindingen blijft groter dan wat het beschikbare geheugen kan toewijzen zonder werkgeheugen of gedeelde buffers in gevaar te brengen.

In deze drie gevallen is het juiste antwoord bijna altijd een pooler die tussen de applicatie en Postgres is geplaatst, en niet een hogere max_connections. Onze vergelijking PgBouncer, Supavisor en PgCat beschrijft de drie opties, en onze gids voor transactiemodus legt de meest voorkomende compromissen uit zodra de pooler eenmaal is geïnstalleerd. Voor alle Postgres-tuning die verder gaat dan verbindingen, zie onze productie Postgres-tuningchecklist.

#
Veelgestelde vragen

Veelgestelde vragen

Wat zijn de standaard max_connections van PostgreSQL?+
100, waarbij standaard 3 verbindingen zijn gereserveerd voor de superuser (superuser_reserved_connections). Deze standaard is geschikt voor veel applicaties die door een pooler gaan, maar wordt al snel onvoldoende zonder pooling zodra een reeks applicatieprocessen elk hun eigen batch verbindingen opent.
Kunnen we max_connections wijzigen zonder PostgreSQL opnieuw te starten?+
Nee. max_connections is een postmaster-contextparameter: Postgres leest deze één keer bij het opstarten om het gedeelde geheugen te vergroten. ALTER SYSTEM SET schrijft de nieuwe waarde naar postgresql.auto.conf, maar alleen een volledige herstart van de server past deze toe; een herlaadbeurt of een SIGHUP zijn niet genoeg.
Hoeveel geheugen verbruikt een inactieve PostgreSQL-verbinding?+
Er is geen enkel officieel nummer: het hangt af van work_mem, shared_buffers en extensies die per sessie worden geladen. Wat echter is gedocumenteerd, is dat work_mem wordt toegewezen per sorteer- of hash-bewerking in een query, en niet per verbinding: een enkele complexe query kan daarom work_mem meerdere keren verbruiken op een enkele actieve verbinding.
Moeten we altijd de voorkeur geven aan een pooler als PgBouncer boven een hogere max_connections?+
In de meeste gevallen wel, zodra het aantal daadwerkelijke clientverbindingen de ideale gelijktijdigheid, berekend door de PostgreSQL-wikiformule, aanzienlijk overschrijdt. Een transactiemoduspooler bundelt een klein aantal fysieke verbindingen tussen een veel groter aantal logische verbindingen aan de applicatiezijde. Bekijk onze vergelijking van PgBouncer, Supavisor en PgCat om te kiezen welke.
Wat meet de formule (kernen × 2) + efficiënte schijven precies?+
Het schat de ideale actieve gelijktijdigheid: het aantal verzoeken dat de CPU en schijf van een bepaalde server parallel kunnen verwerken zonder de doorvoer te verminderen, niet het totale aantal verbindingen dat moet worden geopend in max_connections. Dit is een startpunt dat moet worden gevalideerd door meting, gedocumenteerd door de officiële PostgreSQL-projectwiki, en geen harde limiet.
Hoe weet ik of mijn Postgres-server de verbindingslimiet bijna heeft bereikt?+
Voer een query uit op pg_stat_activity en vergelijk het aantal verbindingen in actieve status met die in inactieve status. Een groot aantal inactieve verbindingen nabij de max_connections-limiet, zonder actief verzoek erachter, duidt bijna altijd op de noodzaak om te poolen in plaats van op de noodzaak om max_connections verder te verhogen.

KLAAR VOOR IMPLEMENTATIE?

Uw backend in vijf minuten.

Geen creditcard vereist · 500 MB gratis · 50.000 MAU