Repository navigation
Measure prod memory, swap and CPU for 7 days before any compute change #324
Description
Key: SPR-17 · Type: HITL · Part of: #327 · Blocked by: none · Checked against: 3bb26de
Problem
Compute size is the only thing that changes our Supabase bill, and nobody has ever measured prod memory, swap or CPU. The July 2026 audit estimated 70-90% RAM use on the Small size. That number is a guess, not a reading. This issue collects 7 days of host metrics from the Supabase dashboard. It ends with one recorded ruling on this issue: keep, upsize or (later) downsize.
Until this ruling exists, nobody may propose a compute change. That includes the "downgrade to Micro" idea on the #326 do-not-do list.
Context
Tags: [prod] measured on prod · [docs] Supabase documentation, checked 2026-09-28 · [pred] inferred or estimated, not measured.
How Supabase bills compute [docs]. "You are charged for the Compute resources of that server, independent of your database usage." Source: https://supabase.com/docs/guides/platform/manage-your-usage/compute. So query tuning saves $0. Only the size changes the bill.
| Size | Memory | CPU | Max direct connections | Price per month [docs] |
|---|---|---|---|---|
| Micro | 1 GB | Shared | 60 | about $10 |
| Small | 2 GB | Shared | 90 | about $15 |
| Medium | 4 GB | Shared | 120 | about $60 |
- Paid plans include $10 a month in compute credits, not carried over [docs]. If prod is the only project using them, Small costs about $5 net and Micro about $0.
- "Compute instance changes are usually applied with less than 2 minutes of downtime, but can take longer depending on the underlying Cloud Provider." [docs] Source: https://supabase.com/docs/guides/platform/compute-and-disk.
What we know about prod (project tglymsfloxmouzjuoycu, Postgres 15.8.1.073).
| Fact | Value | Tag |
|---|---|---|
| Compute size | Small (2 GB, shared cores) | [pred] inferred from max_connections = 90, the Small value. Never read from the dashboard. |
max_connections |
90 | [prod] 2026-09-28 |
| Connections in use | 27 on 2026-09-28; 29 on 2026-07-17 | [prod] |
shared_buffers |
655,368 kB (about 640 MB) on 2026-09-28; 512 MB on 2026-07-17 | [prod] |
effective_cache_size |
1,966,088 kB (about 1,920 MB) on 2026-09-28; 1,536 MB on 2026-07-17 | [prod] |
work_mem |
5 MB | [prod] |
| Database size | 62 MB | [prod] |
| SQL CPU | 35.0 s of DB time per hour = 0.97% of one core, over a 69.8-minute window | [prod] |
| Host RAM used | 70-90% of 2 GB at near-idle | [pred] July 2026 estimate, never measured |
| Host swap, host CPU | unknown | not measured |
Two points need attention:
- SQL CPU is not the constraint. It excludes PostgREST, Auth, Kong and Realtime on the same host. Host CPU is still unmeasured.
shared_buffersgrew from 512 MB to about 640 MB between July and September.effective_cache_sizegrew from 1,536 MB to about 1,920 MB. The Small ratios are 25% and 75% of 2 GB. The new values do not fit those ratios. Either Supabase changed its defaults, a custom override exists, or the size is not Small. Step 2 checks this. A larger buffer pool also leaves less RAM for the other services.
Supabase's rules for "too small" [docs].
- "If your swap is above 70%, chances are high that your compute hardware is not suitable for your workload." Source: https://supabase.com/docs/guides/troubleshooting/exhaust-ram.
- High swap matters when the instance is "consistently using more than 75%" of RAM. "High Swap is usually not a problem unless other resources (such as RAM) are constrained." Source: https://supabase.com/docs/guides/troubleshooting/exhaust-swap.
- On the 1 GB size, about 50% base memory use is normal, from the services that run next to Postgres [docs].
- The docs name the dashboard page "Database Health in the Observability section". The metric names for swap activity are
node_vmstat_pswpinandnode_vmstat_pswpout[docs].
What to do
Agents have no prod or dashboard access. Every step is [maintainer]. This issue changes no repo file.
-
[maintainer] Confirm the size. Open the Supabase dashboard, project
tglymsfloxmouzjuoycu, then Project Settings → Compute and Disk. Record the compute size and any add-on. While there, record two pool sizes without changing them: Settings → Database → Connection pooling (pool size) and Settings → Realtime (database pool size). -
[maintainer] Explain the buffer settings. First list the custom overrides with the Supabase CLI. It reads through the Management API, needs your CLI login, and changes nothing:
cd packages/supabase bunx supabase postgres-config get --project-ref tglymsfloxmouzjuoycuThen run this read-only SQL in the dashboard SQL editor:
select name, setting, unit, source from pg_settings where name in ('shared_buffers', 'effective_cache_size', 'max_connections', 'work_mem', 'maintenance_work_mem'); select count(*) as backends, coalesce(application_name, '') as app from pg_stat_activity group by 2 order by 1 desc;
Post only the memory settings from both reads. Post no other override values, because the repo is public. If
postgres-config getlistsshared_buffersoreffective_cache_size, a custom override explains the change. If it lists neither, and the size is Small, Supabase changed its default. Overrides persist across a size change, so record them before any ruling. -
[maintainer] Start the 7-day window. Open Observability → Database Health (or Reports → Infrastructure, if that is where the chart appears). Record the start time in UTC. The window must not span a Postgres upgrade (Upgrade prod Postgres from 15.8.1.073 #322), a compute change or a project restart. If one happens, restart the window.
-
[maintainer] Record once a day for 7 days. Set the chart range to the widest available. If it shows 7 days at once, one reading at the end is enough. Otherwise fill one row per day:
Day (UTC date) Memory used % avg Memory used % peak Swap used % peak Swap rising? (yes/no) CPU % avg CPU % peak Backends (sum of the step 2 pg_stat_activitycounts)Events that day (deploys, incidents) -
[maintainer] Apply the decision table and post the ruling. Post the filled table and one ruling line as a comment on this issue. Update the Measure prod memory, swap and CPU for 7 days before any compute change #324 row in [Tracking] Supabase prod security and performance review, 2026-09-28 #327.
Read the rows top to bottom. The first row wins over all others. The Micro row can apply together with the Keep row. The CPU row is independent of the size rows.
Observed over the 7 days Reading Money Action The dashboard shows a size other than Small The inference was wrong depends Record the real size. Redo this table with that size's RAM. Swap above 70% on 2 or more days Too small [docs rule; the day count is a pred threshold] +$45 a month (Small to Medium) Upsize to Medium in the Upgrade prod Postgres from 15.8.1.073 #322 maintenance window, so the downtime happens once. Memory used consistently above 75% and swap rising Too small [docs rule] +$45 a month Same as the row above. Swap at or under 70% (one-day spikes allowed), memory high but flat Small fits. High memory is cache and base services. $0 Keep Small. Close this issue. Memory peak under 800 MB (40% of 2 GB), swap 0 all 7 days, backends 45 or fewer Micro might fit [pred threshold, not from docs] saves about $5 a month Keep Small for now. Open a separate issue for a Micro ruling. Do not downsize in this issue. CPU peak above 80% on 3 or more days Not a billing signal on its own $0 Keep the size ruling. Open a separate issue to find the CPU user. A one-day swap spike can come from a backup or a restart. Note its cause in the "Events" column. The Micro row and the day counts are thresholds this issue proposes, not Supabase rules. Micro has 1 GB, and the base services use about half of it [docs].
Out of scope
- The Postgres upgrade and its maintenance window: Upgrade prod Postgres from 15.8.1.073 #322. An upsize, if ruled, rides that window.
- The 13-15 s
realtime.list_changesspikes: Find the cause of the 13-15 s realtimelist_changesspikes #325. - The cron-health sampling change (60 s to 180 s): Ship and measure the cron-health sampling change #323. Its effect on memory is negligible.
- Parked query changes and the do-not-do list, including "Downgrade to Micro now": Parked Supabase query changes and when to reopen them #326.
- Scraping the Supabase Metrics API into our own Prometheus for continuous host metrics. Open a new issue only if the maintainer asks for it.
- Any change to the Realtime or Supavisor pool sizes. Step 1 only reads them.
Acceptance criteria
- The compute size and any add-on, read from Project Settings → Compute and Disk, are posted on this issue.
- The step 2 memory settings are posted:
postgres-config getmemory rows, and thepg_settingsrows withsource. No other override values are posted. - The 512 MB to 640 MB
shared_bufferschange has a stated cause (Supabase default, custom override, or different size). - A 7-day table with memory, swap and CPU (average and peak) is posted, with the window start and end in UTC.
- The window does not span a Postgres upgrade, a compute change or a restart.
- One ruling line names the matching decision-table row and the action.
- The Measure prod memory, swap and CPU for 7 days before any compute change #324 row in [Tracking] Supabase prod security and performance review, 2026-09-28 #327 shows the ruling.
Verification
- The dashboard compute size matches the size named in the ruling comment.
- Re-run the step 2
pg_settingsquery.max_connectionsmust match the size table in Context: 60 for Micro, 90 for Small, 120 for Medium. - The posted table has 7 consecutive UTC days, or one 7-day chart reading with its range shown.
- If the ruling was an upsize: after the change, Database Health shows swap under 70% for 24 hours. Post that reading on this issue.
House rules
- Prod is the maintainer's. Agents never run SQL on prod and never call a Supabase MCP tool. Every prod step here is read-only except a ruled size change.
- Smallest change that meets the ask. This issue measures and rules; it adds no scripts, dashboards or scrape jobs.
- Simplified English in the ruling comment: short sentences, one name per thing.
- Public issue: post no secrets, keys or personal data from the dashboard or the SQL results.
- Bun only, if any command is needed (
bun,bunx); nevernpmornpx.
Activity