At a glance
This card reports how many SQL statements your Supabase Postgres database is executing per second, live. Where the PostgREST request rate measures how many API calls arrive, this measures the database work those calls (plus Edge Functions, scheduled jobs, Auth, and anything else with a connection) actually generate. It is the single best headline for “how hard is the database working right now?”. For a platform or SRE team it is the load gauge that sits beneath every latency, cache, and capacity card: a latency change is a regression or a load story depending on whether QPS moved with it. It carries no fixed alert because raw throughput is neither healthy nor unhealthy on its own; it is the denominator that makes the rest of the connector interpretable.
Calculation
QPS is a delta of cumulative counters divided by elapsed time:pg_stat_database (xact_commit, xact_rollback) and per-statement call counts in pg_stat_statements (calls). The lifetime totals are dominated by history and barely move, so the card takes the difference between two polls and divides by the time between them. That delta is what makes the reading “live”: a fresh surge or a sudden idle shows up promptly rather than being buried under months of accumulated counts.
Two points shape how to read it:
- This is broader than the API. PostgREST is one source of queries, but Edge Functions, scheduled jobs (pg_cron), the Auth service, Storage metadata, and any direct database connection all execute statements that count here. That is why database QPS is usually higher than PostgREST Request Rate (req/sec), and why a QPS spike with a flat API request rate points at a non-API source: a cron job, a migration, or a background worker.
- The ratio to API requests is diagnostic. Divide database QPS by PostgREST request rate to get queries-per-request. A creeping ratio is the classic signature of an N+1 pattern, where one API call quietly fans out into many database round trips (embedded resources, RLS policies that query other tables, app code looping over rows). Watching the ratio, not just the absolute QPS, catches efficiency regressions early.
Worked example
A platform team runs a Supabase project for a SaaS product. Database QPS normally tracks the API request rate at roughly 4 queries per request and peaks around 1,200 QPS. Snapshot taken on 05 May 26 at 10:50 BST after the on-call dashboard flagged an unusual climb.
There is no alert on this card, but the shape is the lead signal. The team reads it together with the siblings:
- QPS nearly quadrupled while the API request rate barely moved. PostgREST went 190 to 210 req/sec (normal) but database QPS went 760 to 2,950. The extra work is not coming from more API calls; each call is now generating far more queries. The queries-per-request ratio jumped from 4.0 to 14.0.
- That ratio is the smoking gun. A request that used to make 4 queries now makes 14. That is the textbook signature of an N+1 regression: a recent change introduced a loop that fetches related rows one at a time instead of in a single joined query. Cross-referencing PostgREST API Latency p95 (ms), latency has started creeping up as the extra round trips add overhead and the cache hit rate slips.
- It is a code regression, not a load event. Because the API request rate is flat, scaling the tier or the pool would only paper over it. The fix is to collapse the N+1 back into a single query (a PostgREST embedded select, or a join), which restores both QPS and latency.
pg_stat_statements (a low-cost query whose calls had exploded), shipped a fix that fetched the related rows in one embedded select, and QPS dropped back to its normal ratio while latency recovered. The absolute QPS number was the alarm; the queries-per-request ratio was the diagnosis.
Three takeaways:
- Database QPS is broader than API load. It counts every statement from every connection: API, Edge Functions, cron, Auth, direct clients. A QPS spike with flat API traffic points at a non-API source.
- Watch the ratio to request rate, not just the number. Queries-per-request rising at constant API load is the cleanest early sign of an N+1 or chatty-endpoint regression, long before latency makes it obvious.
- Scaling does not fix a code regression. If the extra QPS comes from more queries per request rather than more requests, a bigger tier just delays the problem. Collapse the fan-out at the source.
Sibling cards
Reconciling against the source
Where to look in Supabase’s own tooling:In the Supabase dashboard, open Reports → Database for the query-throughput and transaction charts. The dashboard load charts and this card draw on the same Postgres activity counters. Compute it yourself from the system catalogs:Why our number may legitimately differ from Supabase’s own view:SELECT xact_commit + xact_rollback AS txns FROM pg_stat_database WHERE datname = current_database();sampled twice and differenced gives transactions per second;pg_stat_statementssum(calls)differenced gives statements per second (the closer match to QPS). To attribute the QPS, orderpg_stat_statementsbycallsto see which statements dominate, and checkpg_stat_activityfor what is currently running and from which application. The managed-service console exposes equivalent throughput charts under the project’s observability section; confirm the chart is counting statements (not transactions or connections) over a matching interval before comparing.
Known limitations / FAQs
Why does this card have no alert? Because raw QPS is neither healthy nor unhealthy on its own: 3,000 QPS is excellent on a well-provisioned project and a crisis on a tiny one. The card stays alert-free so it can act as neutral load context for the latency, cache, and capacity gauges, which is where the pass/fail judgement lives. If you want to catch a runaway surge or a drop to zero, add a custom ceiling or floor in the Alert Rules tab tuned to your project’s real pattern. My QPS spiked but my PostgREST request rate did not. What happened? Something other than the API is generating queries. The common sources are a scheduled job (pg_cron), a migration or backfill, a background worker, an Auth-heavy event, or a direct database connection from a script. Orderpg_stat_statements by calls to see which statement jumped, and check pg_stat_activity for the application_name behind it. A QPS spike at flat API traffic almost always traces to a non-API client.
Database QPS is much higher than my API request rate. Is that a problem?
Not inherently, one API call legitimately makes several queries. It becomes a problem when the ratio rises over time at constant API load, which signals an N+1 pattern: an endpoint quietly fanning out into more and more queries (embedded resources, RLS policies that query other tables, app loops). Track queries-per-request, not just absolute QPS, and investigate when the ratio climbs.
Does this count queries from Edge Functions and cron jobs?
Yes. The card counts statements from every connection to Postgres: PostgREST, Edge Functions, pg_cron, the Auth service, Storage metadata, and any direct client. That breadth is the point, it is the true database load, not just the API slice. To isolate the API portion, compare against PostgREST Request Rate (req/sec).
Why is the card’s QPS different from my pg_stat_database query?
Most likely you are comparing statements with transactions. pg_stat_database exposes transaction counts (xact_commit + xact_rollback); the card counts statements, and one transaction can hold many statements, so the card reads higher. Also, a hand-run query on pg_stat_database shows lifetime totals since the last reset, which move slowly, whereas the card uses the live delta. For a like-for-like statement rate, difference sum(calls) from pg_stat_statements across two samples.
My QPS dropped to near zero. Is the database down?
Possibly, but check the benign causes first. A drop to zero can mean the application stopped sending traffic (a broken deploy, a gateway dropping requests upstream), a maintenance window, or, on a Free-tier project, the project pausing after inactivity. Confirm with Project Uptime and PostgREST Request Rate (req/sec) before assuming a database outage.
Can high QPS by itself cause problems even if every query is fast?
Yes. Very high QPS pressures connections (each query needs one), CPU, and the cache even when individual statements are cheap. Watch Supavisor Pool Saturation % and Buffer Cache Hit Rate % alongside QPS; a sustained climb toward your tier’s limits is the signal to optimise the chattiest endpoints or move up a tier before latency breaks.