Skip to content

Measure prod memory, swap and CPU for 7 days before any compute change #324

Open

Description

@HMarzban

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_buffers grew from 512 MB to about 640 MB between July and September. effective_cache_size grew 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_pswpin and node_vmstat_pswpout [docs].

What to do

Agents have no prod or dashboard access. Every step is [maintainer]. This issue changes no repo file.

  1. [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).

  2. [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 tglymsfloxmouzjuoycu

    Then 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 get lists shared_buffers or effective_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.

  3. [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.

  4. [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_activity counts) Events that day (deploys, incidents)
  5. [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

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 get memory rows, and the pg_settings rows with source. No other override values are posted.
  • The 512 MB to 640 MB shared_buffers change 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_settings query. max_connections must 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); never npm or npx.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions