PRODSuwerenna europejska platforma BaaSOtwórz Panel →

Wydajność · 11 min odczytu

PostgREST: benchmark i realne limity w produkcji

Affane Daylami · Fondateur · 18 maja 2026

Powrót do bloga

Sam PostgREST prawie nigdy nie jest wąskim gardłem. W dedykowanych instancjach Aurabase replika działa z 50 do 250 milirdzeniowymi procesorami i 64 do 128 MB pamięci RAM. Jest to lekki plik binarny Haskell, który tłumaczy żądania HTTP na SQL i nic więcej. Prawdziwe ograniczenia pojawiające się w produkcji leżą gdzie indziej. Najczęściej pojawiają się cztery z nich: budżet na połączenia Postgres, które zużywają jego repliki, oraz koszt dokładnej COUNT w MVCC. Obcięcie odpowiedzi może również pozostać niewidoczne w nagłówkach, podobnie jak okno opóźnienia po każdej migracji schematu.

Ten tekst w języku angielskim został wygenerowany automatycznie na podstawie francuskiego oryginału i nie był jeszcze recenzowany.
Ta strona została przetłumaczona automatycznie. Wersja angielska jest miarodajna.

Nasz artykuł na temat kompatybilności z PostgREST opisuje szczegółowo, co serwer obejmuje funkcjonalnie (filtry, osadzanie, RPC, RLS) i co pozostawia Tobie. Ten pochodzi skądś indziej. Dokumentuje, korzystając z kodu Aurabase i oficjalnej dokumentacji PostgREST jako źródeł, gdzie i dlaczego PostgREST faktycznie osiąga plateau na dużą skalę. Nie odtwarzamy tutaj banku obciążenia, którego sami nie uruchomiliśmy. Nasza metodologia testów porównawczych wyjaśnia, dlaczego izolowana liczba, bez opublikowanego protokołu, nie wydaje nam się wiarygodna.

Najważniejsze

  • Sam PostgREST jest lekki: od 50 do 250 milirdzeniowych procesorów, od 64 do 128 MB pamięci RAM na replikę w dedykowanych instancjach Aurabase. Surowa przepustowość HTTP prawie nigdy nie jest czynnikiem ograniczającym w produkcji.
  • Prawdziwy pułap to budżet połączeń Postgres: PGRST_DB_POOL × repliki. Zweryfikowano w kodzie Aurabase: 20 połączeń na projekt na poziomie dedykowanym (10×2), 4 na poziomie współdzielonym (2×2). Jest to celowy wybór, aby zmieścić więcej dzierżawców w tym samym max_connections.
  • Prefer: count=exact wymusza kosztowne skanowanie MVCC na dużych tabelach. PostgREST dokumentuje dwie tańsze alternatywy: count=planned i count=estimated, których koszt jest przybliżony.
  • Pułap db-max-rows (domyślnie 1000 linii w Aurabase) obcina odpowiedź BEZ zgłaszania tego w Content-Range (mierzone w warunkach rzeczywistych, szczegółowo opisane poniżej).
  • Po migracji DDL pamięć podręczna schematu PostgREST jest ładowana asynchronicznie. Brama Aurabase ponawia próbę do 8 razy (łącznie około 3,5 sekundy w najgorszym przypadku), zanim się poddaje, co jest zachowaniem udokumentowanym bezpośrednio w kodzie.
#
Metodologia

Co mierzy benchmark PostgREST, a czego nie mierzy

Test przepustowości HTTP na PostgREST mierzy głównie Postgres, rzadko PostgREST. Serwer to cienka warstwa tłumaczeń przed bazą. W zdecydowanej większości rzeczywistych obciążeń czas odpowiedzi jest zdominowany przez wykonane zapytanie SQL, a nie proces, który je wygenerował.

Projekt PostgREST utrzymuje dedykowane repozytorium dla tego tematu, PostgREST/postgrest-benchmark na GitHubie, które śledzi zmiany przepustowości od wydania do wydania, zamiast publikować izolowane dane marketingowe. Nie wykonaliśmy go tutaj ani nie opublikowaliśmy ponownie. Jego wyniki zależą od sprzętu, rozmiaru schematu i testowanego scenariusza, a dokładnie od zmiennych, które nasz własny protokół porównawczy wymaga udokumentowania przed podaniem liczby.

Poniżej PostgREST znajduje się pgbench, który mierzy warstwę, która naprawdę ma znaczenie: czas transakcji SQL przy jednoczesnym obciążeniu. To jest oficjalne narzędzie do testowania PostgreSQL (postgresql.org/docs/current/pgbench.html, dostęp: 24 sierpnia 2026). Zamiast reprodukować tutaj ten protokół, ten artykuł dokumentuje cztery konkretne ograniczenia architektoniczne PostgREST w produkcji, każde zweryfikowane w kodzie źródłowym Aurabase lub w oficjalnej dokumentacji projektu.

#
Sprawdzone w kodzie

Rzeczywisty ślad instancji PostgREST w Aurabase

Każdy projekt silnika Aurabase Postgres otrzymuje dwie dedykowane repliki PostgREST, kolokowane z jego klastrem. Manifest Kubernetes, który je wdraża, ustawia skromne zasoby.

50-250m
Procesor NA REPLIKĘ
żądania → limity
64-128
MB RAM NA REPLIKĘ
żądania → limity
2
REPLIKI WEDŁUG PROJEKTU
wysoka dostępność (P22)

To, co te repliki tak naprawdę zużywają, to nie procesor: są to połączenia z podstawową bazą Postgres. Każda instancja PostgREST łączy się bezpośrednio z instancją podstawową (-rw), bez przechodzenia przez moduł puli PgBouncer wdrożony dla dzierżawcy. Wybór ten został już szczegółowo opisany w naszym artykule na temat kompatybilności PostgREST: mechanizm przeładowywania schematu LISTEN/NOTIFY wymaga trwałego połączenia, niekompatybilnego z modułem puli w trybie transakcyjnym. Co dodaje ten artykuł: ile to faktycznie kosztuje pod względem połączeń i gdzie osiąga szczyt.

Rozmiar tej puli na replikę (PGRST_DB_POOL) celowo różni się w zależności od poziomu projektu, zweryfikowanego w k8s_tenant.rs, funkcji budującej manifest PostgREST dla każdego projektu:

ŁożyskoPGRST_DB_POOL / replikaReplikiPołączenia / przebudzony projekt
Dedykowane (premium, A1)10 (domyślnie PostgREST)220
Udostępnione (flota, bezpłatna/pro/zespół)2 (domyślny Aurabase, obniżony)24
deploy/cnpg/tenant-postgrest.yaml (ekstrakt prawdziwy, wartość podstawiona przez zleceniodawcę)yaml
# Odcisk palca połączeń na replikę na serwerze podstawowym.
env:
  - { name: PGRST_DB_POOL, value: "PGRST_DB_POOL_VALUE" }  # 10 (dedykowane) lub 2 (wspólne)

Na poziomie dedykowanym ograniczenie jest złagodzone: projekt ma własny klaster CNPG, a zatem własny max_connections, bez żadnych sąsiadów do stracenia. Na wspólnym poziomie kilka projektów z tej samej organizacji znajduje się w jednym klastrze: to właśnie ten kontekst decyduje o budżecie połączeń, co opisano w następnej sekcji.

#
Prawdziwy sufit

Budżet połączeń decyduje o tym, ilu najemców jest uruchomionych w tym samym czasie

We współdzielonym klastrze Postgres to nie przepustowość HTTP ogranicza liczbę jednocześnie aktywnych projektów. Jest to liczba połączeń, które ich instancje PostgREST utrzymują otwarte na serwerze podstawowym, w porównaniu z dostępnym max_connections.

Aurabase oblicza ten budżet bezpośrednio z rzeczywistych limitów klastra, zaznaczonych w fleet.rs: (max_connections − réserve superuser/CNPG − connexions réservées au pooler) ÷ connexions par projet éveillé, piętro na poziomie 1. Stała rezerwa wynosi 10 połączeń (superużytkownik, menedżer instancji CNPG, eksporter metryk, margines administratora dostawcy usług). W przypadku dostarczonych defektów (pula 2 na replikę, 2 repliki lub 4 połączenia na przebudzony projekt) obliczenia dają trzy różne budżety w zależności od poziomu rozmiaru klastra.

Budżet dla jednocześnie aktywnych projektów według poziomu, współdzielony klaster PostgresPoziom bezpłatny: 5 jednocześnie aktywnych projektów (max_connections 50, Pooler 20). Poziom profesjonalisty: 7 (max_connections 100, Pooler 60). Poziom drużyny: 10 (max_connections 200, bilardzista 150). Formuła wywodząca się z kodu Aurabase (fleet.rs::derive_wake_budget), stała rezerwa 10 połączeń, 4 połączenia na projekt wake.024681012bezpłatnie (max_connections 50)5 projektówprofesjonalista (max_connections 100)7 projektówzespół (max_connections 200)10 projektów

Źródło: na podstawie fleet.rs::derive_wake_budget i wake_budget_for_org_plan, kod Aurabase, ponownie przeczytany 24 sierpnia 2026 r.

Budżet ten nie jest kwotą posiadanych projektów: organizacja team może prowadzić 50 projektów, z których większość jest nieaktywna. Jest to ograniczenie współbieżności: liczby projektów, które mogą jednocześnie utrzymywać otwarte połączenia na serwerze podstawowym. Budzenie przekroczenia budżetu nie kończy się niepowodzeniem, jest odkładane do czasu, aż projekt rodzeństwa ponownie przejdzie w tryb uśpienia, zaewidencjonowany w tym samym pliku. Sam temat rozmiaru max_connections został rozwinięty w naszym artykule na temat dostrajania max_connectionsoraz dedykowanego/wspólnego kompromisu jako całości w dedykowanej i współdzielonej bazie.

#
Ukryty koszt

Dlaczego wolisz: count=exact spowalnia zapytanie na dużej tabeli

Pytanie o dokładną sumę zmusza Postgres do zliczania widocznych wierszy przefiltrowanego wyniku przy każdym zapytaniu. Jest to koszt rosnący wraz z tabelą, a nie jest to bezpłatna operacja.

PostgreSQL nie obsługuje żadnych indeksowanych liczników wierszy po wyjęciu z pudełka. W MVCC widoczność wiersza zależy od transakcji, która go odczytuje. Dokładny COUNT(*) musi zatem odwiedzić wiersze kandydujące, a nie odczytywać wstępnie obliczoną wartość. Jest to dobrze udokumentowane ograniczenie strukturalne w ekosystemie Postgres, w tym dostawcy usług analitycznych, tacy jak ClickHouse, którzy porównują swoje własne przybliżone liczniki z zachowaniami transakcyjnymi Postgres.

terminalbash
# Drogie na dużym stole: wymusza skanowanie MVCC przefiltrowanego wyniku
curl "https://<gateway>/v1/db/<project_id>/orders?status=eq.paid" \
  -H "apikey: <clé>" -H "Prefer: count=exact"

# Tańsze alternatywy, udokumentowane przez PostgREST
  -H "Prefer: count=planned"   # wycena za pomocą planera
  -H "Prefer: count=estimated" # zaplanowane powyżej progu, dokładnie poniżej

PostgREST natywnie dokumentuje te trzy strategie liczenia (postgrest.org, dostęp: 24 sierpnia 2026 r.). Strategia exact gwarantuje sumę w cenie skanowania. planned zwraca prawie bezpłatną wycenę z narzędzia do planowania zapytań. estimated automatycznie przełącza się między nimi w oparciu o próg. Wybór nie jest kosmetyczny: paginacja wymagająca count=exact w tabeli zawierającej kilka milionów wierszy płaci za ten skan na każdej stronie, nawet jeśli użytkownik nigdy nie sprawdza ostatniej.

#
Mierzone w realu

Obcięcie wierszy db-max jest niewidoczne bez count=exact

Zakończenie wiersza może obciąć odpowiedź PostgREST bez żadnych wskazówek w treści lub nagłówkach, chyba że wyraźnie zażądano dokładnej sumy. Zmierzyliśmy to w rzeczywistych warunkach na dedykowanej instancji Aurabase, a nie zakładaliśmy.

W 10-wierszowej tabeli testowej z PGRST_DB_MAX_ROWS=5PostgREST v12.2.3 renderuje dokładnie ten sam nagłówek Content-Range w dwóch bardzo różnych sytuacjach:

ZapytanieRenderowane linieZakres treścimeta (Aurabaza)
?limit=50 (bez licznika)5/10, naprawdę0-4/*{}
?limit=50&count=dokładne5/10, naprawdę0-4/10{łącznie: 10}

Bez count=exactodpowiedź składająca się z 5 wierszy jest nie do odróżnienia od tabeli, która tak naprawdę zawierałaby tylko 5: Content-Range: 0-4/* opisuje renderowane wiersze, a nie zastosowany limit. Rzeczywisty obowiązujący limit nie pojawia się w tym przypadku nigdzie, mierzony bezpośrednio na ścieżce PostgREST pakietu Aurabase SDK.

Konsekwencje dla paginacji w PostgREST

Jeśli wdrożenie PostgREST ustawi db-max-rows (domyślna wartość Aurabase to 1000), klient, który porównuje data.length z żądanym limitem w celu wykrycia pełnej strony, może się mylić. Błąd pojawia się, gdy sufit serwera spadnie poniżej tego limitu. Jedynym wiarygodnym sygnałem jest porównanie liczby odebranych linii z total zwróconym przez count=exact, co bezpośrednio uwzględnia kompromis kosztów opisany w poprzedniej sekcji.

#
Odroczone opóźnienie

Ponowne ładowanie pamięci podręcznej schematu po migracji

PostgREST przechowuje schemat Postgres w pamięci podczas uruchamiania. Po operacji DDL (utwórz tabelę, dodaj kolumnę) pamięć podręczną musi zostać ponownie załadowana, zanim nowa trasa odpowie, a to przeładowanie jest asynchroniczne.

Zapis docierający do tego okna może otrzymać przejściowy błąd 404 (pamięć podręczna nie jest jeszcze aktualna), mimo że tabela rzeczywiście istnieje po stronie Postgres. Bramka Aurabase absorbuje to za pomocą ograniczonej pętli ponownych prób, zweryfikowanej w postgrest_proxy.rs: do 8 prób, zwiększając czas oczekiwania (250 ms plus 100 ms na próbę), łącznie 3,5 sekundy w najgorszym przypadku. Mechanizm ten dotyczy tylko zapisów, nigdy odczytów.

Szczegół dokumentowany przez sam kod

Bramka nie wysyła żadnego sygnału przeładowania: tylko czeka. Jedynym prawdziwym wyzwalaczem jest pg_notify('pgrst', 'reload schema') wydany przez usługę bazy danych na ścieżce DDL. Jeśli ścieżka migracji zapomni wyemitować ten sygnał, 8 prób wyczerpie się w pamięci podręcznej, która nigdy się nie zmieni, ryzyko udokumentowane w komentarzu do kodu, a nie ukryte.

W przypadku samodzielnego wdrożenia PostgREST lekcja jest uogólniona. Każda ścieżka DDL w aplikacji powinna wywołać przeładowanie poprzez sygnał NOTIFY lub SIGUSR1 do procesu. W przeciwnym razie migracja powoduje gwałtowny wzrost opóźnienia p99 maskowany jako sporadyczne błędy zaraz po wdrożeniu.

#
Streszczenie

To, co dzieli architektura, a nie surowa przepustowość

Cztery udokumentowane tutaj ograniczenia mają jedną wspólną cechę: żadne nie są widoczne w izolowanym teście przepustowości HTTP, ale wszystkie cztery określają, czy wdrożenie PostgREST skaluje się do środowiska produkcyjnego.

  • Budżet połączenia: ogranicza liczbę dzierżawców aktywnych jednocześnie w klastrze współdzielonym, niezależnie od przepustowości na dzierżawcę.
  • Koszt dokładnej LICZBY: rośnie wraz ze stołem, a nie obciążeniem; jest pomijany za pomocą planned/estimated.
  • Ciche obcięcie: poprawnie skonfigurowany limit wiersza może nadal zakłócać słabo oprzyrządowane stronicowanie.
  • Przeładowanie schematu: okno opóźnienia po każdej migracji, ograniczone, jeśli sygnał przeładowania jest dobrze podłączony, w przeciwnym razie nieograniczone.

Niezależnie od tego, czy wybierasz między hostowanym PostgREST, warstwą GraphQL w stylu Hasura, czy niestandardowym interfejsem API, te cztery osie są lepszym punktem porównania niż izolowana liczba wymagań/s. Zobacz nasze porównanie PostgREST vs Hasura vs niestandardowe API. Wybór Poolera, który stoi przed Twoją bazą danych, jest równie ważny: nasze porównanie PgBouncer vs Supavisor vs PgCat szczegółowo opisuje, dlaczego PostgREST nie może przejść przez Pooler w trybie transakcyjnym.

#
Często zadawane pytania

Często zadawane pytania

Czy PostgREST jest wystarczająco szybki do produkcji na dużą skalę?+
Sam PostgREST jest lekkim procesem. W dedykowanych instancjach Aurabase replika działa z 50 do 250 milirdzeniowymi procesorami i 64 do 128 MB pamięci RAM, co zostało zweryfikowane w manifeście Kubernetes projektu. Surowa przepustowość HTTP prawie nigdy nie jest czynnikiem ograniczającym w produkcji. To budżet połączenia Postgres, koszt dokładnej COUNT i pamięć podręczna schematu określają, czy całość się skaluje, a nie sama prędkość pliku binarnego PostgREST.
Skąd mam wiedzieć, czy moja odpowiedź PostgREST została obcięta przez wiersze db-max?+
Nagłówek Content-Range zwrócony przez PostgREST nigdy tego nie mówi. Odpowiedź ograniczona do 5 wierszy na wiersz db-max jest nie do odróżnienia od tabeli, która w rzeczywistości zawiera tylko 5 wierszy, mierzona w rzeczywistych warunkach na dedykowanej instancji Aurabase. Jedynym niezawodnym sposobem na wykrycie tego jest porównanie liczby otrzymanych linii z sumą zwróconą przez Prefer: count=exact, bez tego nagłówka obcięcie pozostaje niewidoczne.
Czy dokładna liczba COUNT zawsze spowalnia żądanie PostgREST?+
Preferuj: count=exact zmusza Postgres do zliczania widocznych wierszy przefiltrowanego wyniku przy każdym zapytaniu, a koszt wzrasta wraz z rozmiarem tabeli ze względu na MVCC. Postgres nie obsługuje indeksowanego licznika wierszy po wyjęciu z pudełka. PostgREST oferuje dwie tańsze alternatywy, count=planned (oszacowanie za pomocą harmonogramu) i count=estimated (automatyczne przełączanie powyżej progu), udokumentowane w oficjalnej dokumentacji.
Ile połączeń Postgres zużywa PostgREST?+
Zależy to całkowicie od PGRST_DB_POOL pomnożonego przez liczbę replik. Zweryfikowano w kodzie Aurabase: instancja dedykowana (warstwa premium) domyślnie otwiera 10 połączeń na replikę, czyli łącznie 20 na 2 repliki. Poziom współdzielony dobrowolnie obniża tę pulę do 2 na replikę lub 4 połączeń na przebudzony projekt, aby obsłużyć więcej dzierżawców przy tym samym budżecie max_connections klastra udostępnionego.
Czy istnieje oficjalny test porównawczy PostgREST?+
Projekt utrzymuje dedykowane repozytorium PostgREST/postgrest-benchmark na GitHubie, które śledzi zmiany przepustowości od wydania do wydania, zamiast publikować izolowane dane marketingowe. Nie wykonaliśmy go tutaj ani nie opublikowaliśmy ponownie. Ten artykuł dokumentuje zweryfikowane ograniczenia architektoniczne w naszym kodzie i oficjalnej dokumentacji PostgREST, a nie ławkę, którą sami odtworzyliśmy.
#
Wniosek

O czym pamiętać

PostgREST prawie nigdy nie psuje się pod samym obciążeniem HTTP: jego architektura jest na to zbyt prosta. To, co powoduje przerwy w produkcji, to to, co ją otacza: ile połączeń utrzymują otwarte jej repliki, ile dokładnie kosztuje ogółem. Obejmuje to również to, czy obcięcie pozostaje widoczne i jak długo trwa okno po migracji.

Te cztery ograniczenia nie są specyficzne dla Aurabase: mają zastosowanie do każdego wdrożenia PostgREST, zarówno hostowanego samodzielnie, jak i zarządzanego. Ten kod pokazuje, jak wdrożenie z wieloma dzierżawcami sprawia, że ​​są one wyraźne, a nie zaskakujące w środowisku produkcyjnym.

GOTOWY DO WDROŻENIA?

Twój backend w pięć minut.

Karta kredytowa nie jest wymagana · 500 MB za darmo · 50 000 MAU