PRODSoeverein Europees BaaS-platformOpen Dashboard →

Prestaties · 11 min gelezen

PostgREST: benchmark en echte limieten in de productie

Affane Daylami · Fondateur · 18 mei 2026

Terug naar blog

PostgREST zelf is vrijwel nooit het knelpunt. Op speciale Aurabase-instanties draait een replica met 50 tot 250 millicores CPU en 64 tot 128 MB RAM. Het is een lichtgewicht binair bestand van Haskell dat HTTP-verzoeken vertaalt naar SQL, meer niet. De echte grenzen van de productie liggen elders. Vier daarvan komen het vaakst ter sprake: het budget voor Postgres-verbindingen dat de replica's ervan verbruiken, en de kosten van een exacte COUNT onder MVCC. Een reactieafkapping kan ook onzichtbaar blijven in de headers, evenals een latentieperiode na elke schemamigratie.

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.

Ons artikel over PostgREST-compatibiliteit beschrijft wat de server functioneel dekt (filters, insluiten, RPC, RLS) en wat het aan u overlaat. Deze komt ergens anders vandaan. Het documenteert, met Aurabase-code en de officiële PostgREST-documentatie als bronnen, waar en waarom PostgREST feitelijk op grote schaal een plateau bereikt. We reproduceren hier geen loadbank die we niet zelf hebben beheerd. Onze benchmarkmethodologie legt uit waarom een ​​geïsoleerd cijfer, zonder gepubliceerd protocol, ons niet betrouwbaar lijkt.

De essentie

  • PostgREST zelf is lichtgewicht: 50 tot 250 millicores CPU, 64 tot 128 MB RAM per replica op speciale Aurabase-instanties. Raw HTTP-doorvoer is bijna nooit de beperkende factor in de productie.
  • Het echte plafond is het Postgres-verbindingsbudget: PGRST_DB_POOL × replica's. Geverifieerd in de Aurabase-code: 20 verbindingen per project op het speciale niveau (10×2), 4 op het gedeelde niveau (2×2). Dit is een bewuste keuze om meer huurders op dezelfde max_connectionste plaatsen.
  • Prefer: count=exact forceert dure MVCC-scans op grote tafels. PostgREST documenteert twee goedkopere alternatieven: count=planned en count=estimated, die een geschat totaal kosten.
  • Een plafond van db-max-rows (standaard 1000 regels bij Aurabase) kapt een antwoord af ZONDER het te rapporteren in Content-Range (gemeten in reële omstandigheden, hieronder gedetailleerd).
  • Na een DDL-migratie wordt de PostgREST-schemacache asynchroon opnieuw geladen. De Aurabase-gateway probeert het maximaal 8 keer opnieuw (ongeveer 3,5 seconden cumulatief in het ergste geval) voordat hij het opgeeft, een gedrag dat rechtstreeks in de code wordt gedocumenteerd.
#
Methodologie

Wat een PostgREST-benchmark meet en wat niet

Een HTTP-doorvoertest op PostgREST meet voornamelijk Postgres, zelden PostgREST. De server is een dunne vertalingslaag voor de basis. Bij de overgrote meerderheid van de toepassingen in de echte wereld wordt de responstijd gedomineerd door de uitgevoerde SQL-query, en niet door het proces dat deze heeft gegenereerd.

Het PostgREST-project onderhoudt een speciale repository voor dit onderwerp, PostgREST/postgrest-benchmark op GitHub, die doorvoervariaties bijhoudt van release tot release in plaats van een geïsoleerd marketingcijfer te publiceren. We hebben het hier niet uitgevoerd of opnieuw gepubliceerd. De resultaten zijn afhankelijk van de hardware, de schemagrootte en het geteste scenario; precies de variabelen die ons eigen benchmarkprotocol vereist om te worden gedocumenteerd voordat een cijfer wordt geciteerd.

Onder PostgREST staat pgbench, die de laag meet die er echt toe doet: SQL-transactietijd onder gelijktijdige belasting. Dit is de officiële PostgreSQL-benchmarktool (postgresql.org/docs/current/pgbench.html, toegankelijk op 24 augustus 2026). In plaats van dit protocol hier te reproduceren, documenteert dit artikel vier concrete architecturale beperkingen van PostgREST in productie, elk geverifieerd in de Aurabase-broncode of in de officiële projectdocumentatie.

#
Code ingecheckt

De daadwerkelijke voetafdruk van een PostgREST-instantie bij Aurabase

Elk Aurabase Postgres-engineproject ontvangt twee speciale PostgREST-replica's, op dezelfde locatie als het cluster. Het Kubernetes-manifest dat ze inzet, stelt bescheiden middelen vast.

50-250m
CPU PER REPLICA
verzoeken → limieten
64-128
MB RAM PER REPLICA
verzoeken → limieten
2
REPLICA'S PER PROJECT
hoge beschikbaarheid (P22)

Wat deze replica's werkelijk verbruiken is niet de CPU: het zijn verbindingen met de primaire Postgres. Elke PostgREST-instantie maakt rechtstreeks verbinding met de primaire (-rw), zonder de PgBouncer-pooler te doorlopen die voor de tenant is geïmplementeerd. Deze keuze wordt al gedetailleerd beschreven in ons artikel over PostgREST-compatibiliteit: het herlaadmechanisme van het LISTEN/NOTIFY schema vereist een permanente verbinding, die niet compatibel is met een pooler in transactiemodus. Wat dit artikel toevoegt: hoeveel kost het eigenlijk, qua aansluitingen, en waar het piekt.

De grootte van deze pool per replica (PGRST_DB_POOL) verschilt opzettelijk afhankelijk van het projectniveau, geverifieerd in k8s_tenant.rs, de functie die het PostgREST-manifest voor elk project samenstelt:

LagerPGRST_DB_POOL / replicaReplica'sVerbindingen / ontwaakt project
Speciaal (premium, A1)10 (PostgREST-standaard)220
Gedeeld (vloot, gratis/pro/team)2 (Aurabase standaard, verlaagd)24
deploy/cnpg/tenant-postgrest.yaml (echt extract, waarde vervangen door de leverancier)yaml
# Vingerafdruk van verbindingen per replica op de primaire.
env:
  - { name: PGRST_DB_POOL, value: "PGRST_DB_POOL_VALUE" }  # 10 (speciaal) of 2 (gedeeld)

Op het specifieke niveau zijn de beperkingen versoepeld: een project heeft zijn eigen CNPG-cluster, dus zijn eigen max_connections, zonder dat er buren over zijn. Op gedeeld niveau delen meerdere projecten van dezelfde organisatie één cluster: het is deze context die het budget voor verbindingen doorslaggevend maakt, zoals uitgewerkt in de volgende paragraaf.

#
Het echte plafond

Het aansluitbudget bepaalt hoeveel tenants er tegelijkertijd actief zijn

Op een gedeeld Postgres-cluster is het niet de HTTP-doorvoer die het aantal gelijktijdig actieve projecten beperkt. Dit is het aantal verbindingen dat hun PostgREST-instanties openhouden op de primaire verbinding, vergeleken met de beschikbare max_connections.

Aurabase leidt dit budget rechtstreeks af van de daadwerkelijke clusterlimieten, gecontroleerd in fleet.rs: (max_connections − réserve superuser/CNPG − connexions réservées au pooler) ÷ connexions par projet éveillé, minimum op 1. De vaste reserve is 10 verbindingen (superuser, CNPG instance manager, metrics exporter, provisioner admin marge). Voor de geleverde defecten (pool van 2 per replica, 2 replica's of 4 verbindingen per ontwaakt project) levert de berekening drie verschillende budgetten op, afhankelijk van het grootteniveau van het cluster.

Budget voor gelijktijdig actieve projecten per niveau, gedeeld Postgres-clusterGratis niveau: 5 gelijktijdig actieve projecten (max_connections 50, pooler 20). Pro-niveau: 7 (max_connections 100, pooler 60). Teamniveau: 10 (max_connections 200, pooler 150). Formule afgeleid van Aurabase-code (fleet.rs::derive_wake_budget), vaste reserve van 10 verbindingen, 4 verbindingen per wakker project.024681012gratis (max_connections 50)5 projectenpro (max_connecties 100)7 projectenteam (max_connections 200)10 projecten

Bron: afgeleid van fleet.rs::derive_wake_budget en wake_budget_for_org_plan, Aurabase-code, herlezen op 24 augustus 2026.

Dit budget is geen quotum voor projecten in eigendom: een team organisatie kan 50 projecten beheren, waarvan de meeste inactief zijn. Dit is een limiet van gelijktijdigheid: het aantal projecten dat tegelijkertijd open verbindingen kan bevatten op de primaire. Een wake-up over budget mislukt niet; het wordt uitgesteld totdat een zusterproject weer in slaap valt, gecontroleerd in hetzelfde bestand. Het onderwerp van de dimensionering van max_connections zelf wordt uitgebreid besproken in ons artikel over afstemming van max_connections, en de dedicated/gemutualiseerde afweging als geheel in dedicated vs. gedeelde basis.

#
Verborgen kosten

Waarom liever: count=exact vertraagt een zoekopdracht in een grote tabel

Als u om een exact totaal vraagt, moet Postgres bij elke zoekopdracht de zichtbare rijen van het gefilterde resultaat tellen, een kosten die met de tabel meegroeit, en geen gratis bewerking.

PostgreSQL onderhoudt standaard geen geïndexeerde rijtellers. Onder MVCC hangt de zichtbaarheid van een rij af van de transactie die deze leest. Een exacte COUNT(*) moet daarom de kandidaatrijen bezoeken in plaats van een vooraf berekende waarde te lezen. Dit is een goed gedocumenteerde structurele beperking in het Postgres-ecosysteem, inclusief analyseleveranciers als ClickHouse, die hun eigen geschatte tellers vergelijken met het transactiegedrag van Postgres.

terminalbash
# Duur op een grote tafel: forceert een MVCC-scan van het gefilterde resultaat
curl "https://<gateway>/v1/db/<project_id>/orders?status=eq.paid" \
  -H "apikey: <clé>" -H "Prefer: count=exact"

# Goedkopere alternatieven, gedocumenteerd door PostgREST
  -H "Prefer: count=planned"   # schatting via planner
  -H "Prefer: count=estimated" # gepland voorbij een drempel, precies daaronder

PostgREST documenteert deze drie telstrategieën native (postgrest.org, geraadpleegd op 24 augustus 2026). De exact-strategie garandeert een totaal tegen de prijs van de scan. planned retourneert een vrijwel gratis schatting van de queryplanner. estimated schakelt automatisch tussen de twee op basis van een drempelwaarde. De keuze is niet cosmetisch: een paginering die count=exact vereist op een tabel van enkele miljoenen rijen, betaalt voor deze scan op elke pagina, zelfs als de gebruiker de laatste nooit raadpleegt.

#
Gemeten in het echt

Het afkappen van db-max-rijen is onzichtbaar zonder count=exact

Een rijlimiet kan een PostgREST-antwoord afkappen zonder enige indicatie in de hoofdtekst of headers, tenzij expliciet om een exact totaal wordt gevraagd. We hebben het onder reële omstandigheden gemeten op een speciale Aurabase-instantie, en niet aangenomen.

Op een testtabel met 10 rijen met PGRST_DB_MAX_ROWS=5geeft PostgREST v12.2.3 exact dezelfde Content-Range header weer voor twee heel verschillende situaties:

VraagGesmolten lijnenInhoudsbereikmeta (Aurabase)
?limit=50 (zonder telling)5/10 echt0-4/*{}
?limit=50&count=exact5/10 echt0-4/10{totaal: 10}

Zonder count=exactis het antwoord van 5 rijen niet te onderscheiden van een tabel die er eigenlijk maar 5 zou bevatten: Content-Range: 0-4/* beschrijft de weergegeven rijen, nooit de toegepaste limiet. De werkelijke limiet die van kracht is, verschijnt in dit geval nergens, rechtstreeks gemeten op het PostgREST-pad van de Aurabase SDK.

Gevolg voor eventuele paginering op PostgREST

Als uw PostgREST-implementatie een db-max-rows instelt (Aurabase is standaard ingesteld op 1000), kan een client die data.length vergelijkt met de gevraagde limiet om een volledige pagina te detecteren, zich vergissen. De fout verschijnt zodra het serverplafond lager is dan deze limiet. Het enige betrouwbare signaal is het vergelijken van het aantal ontvangen lijnen met de total die wordt geretourneerd door count=exact, wat direct een rol speelt in de kostenafweging die in de vorige sectie is beschreven.

#
Uitgestelde latentie

De schemacache opnieuw laden na een migratie

PostgREST houdt het Postgres-schema bij het opstarten in het geheugen. Na een DDL (tabel maken, kolom toevoegen) moet deze cache opnieuw worden geladen voordat de nieuwe route reageert, en dit herladen is asynchroon.

Een schrijfbewerking die in dit venster binnenkomt, ontvangt mogelijk een tijdelijke 404 (cache nog niet up-to-date), ook al bestaat de tabel inderdaad aan de Postgres-kant. De Aurabase-gateway absorbeert dit met een begrensde herhalingslus, geverifieerd in postgrest_proxy.rs: maximaal 8 pogingen, toenemende backoff (250 ms plus 100 ms per poging), 3,5 seconden cumulatief in het ergste geval. Dit mechanisme heeft alleen invloed op schrijven, nooit op lezen.

Een detail dat de code zelf documenteert

De gateway geeft geen herlaadsignaal af: hij wacht alleen maar. De enige echte trigger is een pg_notify('pgrst', 'reload schema') uitgegeven door de databaseservice op het DDL-pad. Als een migratiepad vergeet dit signaal uit te zenden, worden de acht pogingen uitgeput in een cache die nooit zal veranderen, een risico dat wordt gedocumenteerd zoals in het codecommentaar, en niet verhuld.

Voor een zelf-hostende PostgREST-implementatie is de les generaliseerbaar. Elk DDL-pad in uw toepassing moet het opnieuw laden activeren, via NOTIFY of een SIGUSR1-signaal naar het proces. Anders veroorzaakt een migratie direct na de implementatie een p99-latentiepiek, vermomd als periodieke fouten.

#
Samenvatting

Wat de architectuur snijdt, niet de ruwe doorvoer

De vier hier gedocumenteerde beperkingen hebben één ding gemeen: geen enkele wordt gezien bij een geïsoleerde HTTP-doorvoertest, maar ze bepalen alle vier of een PostgREST-implementatie naar productie kan worden geschaald.

  • Verbindingsbudget: beperkt het aantal tenants dat tegelijkertijd actief is op een gedeeld cluster, ongeacht de doorvoer per tenant.
  • Kosten van exact COUNT: groeit mee met de tafel, niet met de belasting; wordt omzeild met planned/estimated.
  • Stille afkapping: een correct geconfigureerde rijkap kan nog steeds slecht geïnstrumenteerde paging verbreken.
  • Schema herladen: een latentievenster na elke migratie, begrensd als het herlaadsignaal goed bedraad is, anders onbeperkt.

Of u nu kiest tussen zelf-gehoste PostgREST, een GraphQL-laag in Hasura-stijl of een aangepaste API, deze vier assen zijn een beter vergelijkingspunt dan een geïsoleerd req/s-cijfer. Zie onze vergelijking PostgREST versus Hasura versus aangepaste API. De keuze van de pooler die voor uw database staat, is net zo belangrijk: onze vergelijking PgBouncer versus Supavisor versus PgCat legt uit waarom PostgREST niet door een pooler kan gaan in de transactiemodus.

#
Veelgestelde vragen

Veelgestelde vragen

Is PostgREST snel genoeg voor grootschalige productie?+
PostgREST zelf is een lichtgewicht proces. Op speciale Aurabase-instanties draait een replica met 50 tot 250 millicores CPU en 64 tot 128 MB RAM, geverifieerd in het Kubernetes-manifest van het project. Raw HTTP-doorvoer is bijna nooit de beperkende factor in de productie. Het zijn het Postgres-verbindingsbudget, de kosten van een exact COUNT en de schemacache die bepalen of het geheel schaalbaar is, en niet alleen de snelheid van het binaire PostgREST-bestand.
Hoe weet ik of mijn PostgREST-antwoord is afgekapt door db-max-rows?+
De Content-Range-header die door PostgREST wordt geretourneerd, zegt dit nooit. Een respons beperkt tot 5 rijen per db-max-rijen is niet te onderscheiden van een tabel die er eigenlijk maar 5 bevat, gemeten in reële omstandigheden op een speciale Aurabase-instantie. De enige betrouwbare manier om dit te detecteren is door het aantal ontvangen regels te vergelijken met het totaal dat door Prefer wordt geretourneerd: count=exact, zonder deze header blijft de afkapping onzichtbaar.
Vertraagt de exacte COUNT altijd een PostgREST-verzoek?+
Liever: count=exact dwingt Postgres om bij elke zoekopdracht de zichtbare rijen van het gefilterde resultaat te tellen, een kosten die vanwege MVCC toeneemt naarmate de tabel groter wordt. Postgres houdt geen kant-en-klare geïndexeerde rijteller bij. PostgREST biedt twee goedkopere alternatieven, count=gepland (schatting via de planner) en count=geschat (automatisch overschakelen voorbij een drempel), gedocumenteerd in de officiële documentatie.
Hoeveel Postgres-verbindingen verbruikt PostgREST?+
Het hangt volledig af van PGRST_DB_POOL vermenigvuldigd met het aantal replica's. Geverifieerd in de Aurabase-code: een speciale instantie (premiumlaag) opent standaard 10 verbindingen per replica, of 20 in totaal over 2 replica's. Het gedeelde niveau verlaagt deze pool vrijwillig tot 2 per replica, of 4 verbindingen per ontwaakt project, om meer tenants te huisvesten met hetzelfde max_connections budget van het gedeelde cluster.
Is er een officiële PostgREST-benchmark?+
Het project onderhoudt een speciale repository, PostgREST/postgrest-benchmark op GitHub, die de doorvoervariaties van release tot release bijhoudt in plaats van een geïsoleerd marketingcijfer te publiceren. We hebben het hier niet uitgevoerd of opnieuw gepubliceerd. Dit artikel documenteert geverifieerde architecturale beperkingen in onze code en in de officiële PostgREST-documentatie, niet een bank die we zelf hebben gereproduceerd.
#
Conclusie

Wat te onthouden

PostgREST gaat vrijwel nooit kapot onder HTTP-belasting alleen: daarvoor is de architectuur te simpel. Wat in de productie kapot gaat, is wat eromheen zit: hoeveel verbindingen de replica's openhouden, hoeveel een exact totaal kost. Hieronder valt ook of een afknotting zichtbaar blijft en hoe lang het venster na een migratie duurt.

Deze vier beperkingen zijn niet specifiek voor Aurabase: ze zijn van toepassing op elke PostgREST-implementatie, zelfgehost of beheerd. Wat deze code laat zien, is hoe een implementatie met meerdere tenants deze expliciet maakt in plaats van ze verrassend achter te laten in de productie.

KLAAR VOOR IMPLEMENTATIE?

Uw backend in vijf minuten.

Geen creditcard vereist · 500 MB gratis · 50.000 MAU