Skip to content

Supabase compute and disk sizing

A Supabase project stops being affordable or available for one of four reasons: compute throttle, disk throttle, quota, or read-only. This reference covers every compute size and both disk types, then marks per claim whether the behavior comes from the docs or from a live test here - because some of them disagree.

The measured numbers come from a battery written against throwaway projects on the Management API (Free, Pro, and Team orgs; 2026-08-19), each project deleted in the same run. The compute-disk RUNLOG does not record the AWS region; an earlier version of this paragraph named ap-southeast-1, which is the region of the platform-downtime run this page cross-references, not a recorded fact about this one. Claims that were not run are still cited to the docs and labelled as such.

  • Compute never upgrades itself; disk never shrinks. Compute resize is a 1-2 minute window (measured); disk decrease is rejected outright.
  • Disk autoscale grows at 90% usage by a configurable percent (default 50%). That config cannot be read or written through the Management API at all (measured) - the dashboard is the only surface.
  • The Free-plan read-only wall is not the documented 500 MB: measured reads accepted to ~726 MB database size, then ERROR: 25006: cannot execute INSERT in a read-only transaction. Recover with DELETE (TRUNCATE is also blocked), not vacuum alone.
  • The disk modification quota answered 429 with text “once per four hours” (measured) - the docs describe four modifications per rolling 24 hours. Enforcement was nondeterministic across runs.
  • The “Large compute or above” gate on disk IOPS/throughput is UI-only: the API accepted AND applied elevated IOPS on a Micro project (measured, confirmed by follow-up read).
what hurts?CPU at sustained capDisk IO % consumed > 0db outgrows diskbill over quotaupgrade computeraise IOPS / io2grow disk (manual first)spend cap option

Every section below answers one of those branches, with the measured number in the section body.

Prices and recommended database size from the docs.1

SizeHourlyMonthlyCPUMemoryMax database (recommended)
Nano$0$0sharedup to 0.5 GB500 MB
Micro$0.01344~$102-core shared1 GB10 GB
Small$0.0206~$152-core shared2 GB50 GB
Medium$0.0822~$602-core shared4 GB100 GB
Large$0.1517~$1102-core dedicated8 GB200 GB
XL$0.2877~$2104-core dedicated16 GB500 GB
2XL$0.562~$4108-core dedicated32 GB1 TB
4XL$1.32~$96016-core dedicated64 GB2 TB
8XL$2.562~$1,87032-core dedicated128 GB4 TB
12XL$3.836~$2,80048-core dedicated192 GB6 TB
16XL$5.12~$3,73064-core dedicated256 GB10 TB
>16XL--customcustomcustom

Micro through 2XL is shared and burstable; Large and above are dedicated.1 Burstable means spikes are fine until burst credits drain; then baseline governs.

Nano cannot start on a normal paid (Pro) org: the try was rejected with 400 Minimum instance size on paid plans is Micro (measured, create + PATCH + catalogue; instance-sizing I01, 2026-08-17). On a Free org, Nano pauses and restores fine; wake measured ~162-204 s (I04; in the lab’s AGENTS.md, no RUNLOG entry). Two lifecycle rules follow from the same experiment:

  • Do not wake a legacy free-era paused project on a paid org unless you accept that it joins the always-on Micro floor for good. The restore was accepted, ACTIVE_HEALTHY arrived about 30 minutes later, and POST /v1/projects/{ref}/pause then answered 400 {"message":"Project is not free-tier. Please downgrade it to free-tier first and try again."}
    • pause eligibility follows the org’s current plan, not the project’s lineage (I03, 2026-08-18).
  • On a platform-plan org the create default is Nano (224 MB shared_buffers) and that project can pause; do not pass desired_instance_size there. Nano is absent from every addon catalogue because it is not a purchasable or resize target on any plan (instance-sizing addendum 2026-08-24/25, from sfp-platforms S01).

Per-size IO ceiling (docs, unmeasured here)

Section titled “Per-size IO ceiling (docs, unmeasured here)”

Baseline = sustained. Max = burst until credits drain.1

SizeBaseline MB/sMax MB/sBaseline IOPSMax IOPS
Nano526125011,800
Micro1126150011,800
Small222611,00011,800
Medium432612,00011,800
Large795943,60020,000
XL1495946,00020,000
2XL29759412,00020,000
4XL59459420,00020,000
8XL1,1881,18840,00040,000
12XL1,7811,78150,00050,000
16XL2,3752,37580,00080,000

The docs go further up to 24XL/48XL at 3,750 / 5,000 MB/s baseline.1

Per-size pg limits (docs; Micro and Small measured here)

Section titled “Per-size pg limits (docs; Micro and Small measured here)”
Sizerep slotswal sendersmax connectionspooler clients
Nano5560200
Micro5560200
Small5590400
Medium55120600
Large88160800
XL24242401,000
2XL80803801,500
4XL80804803,000
8XL80804906,000
12XL80805009,000
16XL808050012,000

Measured (D01): Micro max_connections 60, max_wal_senders 10, max_replication_slots 10, shared_buffers 256 MB; Small 90 / 10 / 10 / 512 MB - the wal senders and rep slots above are the docs’ plan-wide ceilings; pg’s own floor per size sits lower.1 Downgrading below your replication-slot usage is rejected because the server will not start.1

The order Micro -> Small -> Large -> Small -> Micro was run with REST (anon table read) and Auth health sampled every 250 ms:

opsettleREST max contiguous outageAuth max outage
upgrade Micro->Small105 s1.0 s0 s
upgrade Small->Large61 s17.0 s0 s
downgrade Large->Small61 s0 s0 s
downgrade Small->Micro73 s0 s0 s

Adjacent resize PATCHes are rate-limited independent of rebuild: the second within a window answered 429 We are still processing addon changes, please try again in N minute(s). A separate experiment (platform-downtime D03, 2026-08-04, n=1, 500 ms sampling from a Singapore IPv4 vantage) measured a Micro -> Small resize at 131 s on GET /auth/v1/health (anon key, HTTP 521) and 207 s on the pooler, with REST at zero failed samples.2 That run and D09 disagree on the same endpoint: D09’s /auth/v1/health probe saw 0 s of contiguous outage across four resizes. Different rigs, projects and vantages, so it is a side-by-side run to do. Docs cite “typically less than 2 minutes”.1 The measured restart and resize dwell times per connection path are in the platform operation-cost reference.

Compute is billed hourly (paused projects don’t accrue) and is NOT spend- cap eligible - the cap only bounds eligible usage items.3

gp3io2
Price/GB-month$0.125$0.195
IOPS price$0.024/IOPS-month$0.119/IOPS-month
Throughput125 MB/s incl, then $0.95/MB/s (max 1,000)scales with IOPS
Max IOPS16,000 (from 32 GB size)80,000 (from 80 GB size)
Max size16 TB60 TB
Effective ceilingmin(compute size, provisioned disk)

Provision more than baseline per GB: gp3 +500 IOPS/GB and +0.25 MB/s/IOPS; io2 +1,000 IOPS/GB.1 The lab measured the “Large compute” gate to be UI-only (below).1

Database size = pg_database_size() (tables + indexes + materialized views). Disk = that + WAL + system files + an empty baseline of ~40-60 MB.4 Free plan quota is on the FIRST; paid-plan read-only trips on the SECOND at 95%.4

  • Delete data: database size does not drop until vacuum runs (dead tuples); TRUNCATE drops instantly. Both measured.
  • Disk util endpoint (GET /config/disk/util) answered 200 on Free AND Pro (measured) - usable in org-wide cost probes.

Autoscale: defaults and the missing surface

Section titled “Autoscale: defaults and the missing surface”

Docs describe: trigger 90% usage, grow by growth percent (default 50%), min increment 1 GB, bounded by max size default 8 GB with the spend cap on.4

Measured: the whole thing is invisible to the Management API. On both Pro and Team orgs the autoscale GET returned an empty shape and PUT/POST /PATCH all answered 404. The dashboard’s editable growth/min/max fields are the only mutation surface - unlike the Data API toggle, which the http-tier-lockdown experiment found was the Management API’s db_schema field in disguise, measured in the AWS PrivateLink reference. Tracking these values is a manual IaC exercise.

On the Free tier: measured baseline disk was 2 GB (docs claim 1 GB) and the disk did NOT grow at 90%+ through a fill - here autoscale did not save you from the read-only anyway.4

Increase is OK (HTTP 201, +200 GB cap per change); decrease is refused (HTTP 400, measured).4

Modification quota measured: 429 Database disk can only be modified once per four hours. Last modified at <UTC> - directly contradicting the docs’ “four modifications within a rolling 24-hour window”.4 One run also accepted 5 consecutive increases in one burst; plan for a cooldown you cannot schedule around, and raise the disk before bulk imports bigger than ~1.5x the current database size. HTTP 429 is also the Management API’s general rate-limit signal - a separate mechanism from this quota; its budget and back-off are worked through in the Management API guide.

Free plan (measured): accepts to ~726 MB database size, then a write fails with ERROR: 25006: cannot execute INSERT in a read-only transaction; a SELECT on the management endpoint answered 201 the whole time. The documented 500 MB was not the boundary in this run,4 and recovery required DELETE (TRUNCATE was rejected) or the override GUC set default_transaction_read_only = 'off' once below the threshold.4

Paid plans: docs trigger at 95% disk util (not run here).4

Disk IOPS/throughput gate (dashboard-only)

Section titled “Disk IOPS/throughput gate (dashboard-only)”

Dashboard: “Adjusting your disk configuration requires LARGE Compute size or above.” Measured: the raise was accepted AND stuck on Micro, verified by follow-up GET. The gate is a UI gate; a PAT bypasses it silently, and IOPS billing starts regardless.

Spend cap (and where compute/disk escape it)

Section titled “Spend cap (and where compute/disk escape it)”

Spend cap ON = eligible overages blocked past quota after notification + grace period, ending in Fair Use restriction; it is billing-path enforcement, not a request-path breaker (measured).3

Exclusions (never capped): compute hours, disk throughput, disk IOPS-hours, custom domains, PITR, read replicas, IPv4, branching, advanced MFA/SSO, log drains.3 Team plan has no spend cap at all - overages are simply billed.3

Each practice names the module it rests on; module ids resolve in the compute-disk RUNLOG and the instance-sizing RUNLOG. A line marked “docs” or “design choice” is not a measurement.

  • Pre-bulk-import: measure; if the import is larger than ~1.5x the current database size, expand the disk manually first (single POST), or the quota kills it mid-import and read-only follows. Then re-check the quota status before a second attempt (D03 quota; D06 read-only).
  • Schedule the next disk change from the 429 body: the quota message carries Last modified at <UTC>, so parse the timestamp and schedule from it rather than re-trying blind (D03).
  • Resize sequencing: wait >= 2 minutes between adjacent resize PATCHes, or the second returns 429 with still processing (D09).
  • Poll for ACTIVE_HEALTHY after a resize with GET /v1/projects/{ref} instead of sleeping a fixed time: settle ran 61-105 s across four operations (D09) and 107 s on D01.
  • Size client retries for the resize gap: REST dropped during both upgrades, 1.0 s of contiguous failure on Micro -> Small and 17.0 s on Small -> Large; both measured downgrades were 0 s. The default supabase-js client took 4 attempts and ~7.0s to ride out three 503s (edge-resilience W02); whether it survives a 17.0 s gap was not measured (D09; W02).
  • Rehearse the resize mechanics on a downgrade if you need a cheap dry run - PATCH, settle, 429 spacing - not the outage: both measured downgrades produced 0 s of REST outage (Large -> Small, Small -> Micro) while both upgrades did not (D09).
  • Read the addon GET for null when returning to Micro, not for ci_micro: Micro is the absence of a compute addon (platform-downtime D04).
  • Do not wake a legacy free-era paused project on a paid org unless you accept it can never be re-paused: 400 Project is not free-tier after a ~30 minute wake (instance-sizing I03).
  • Do not pass desired_instance_size on a platform-plan org: the create default there is Nano, which can pause; Nano is in no addon catalogue on any plan (instance-sizing addendum 2026-08-24/25).
  • Alert on database size, not disk utilisation, on Free projects below ~700 MB: read-only hit at ~726 MB of database size on a 2 GB disk and autoscale did not fire during the fill (D05, D06); /config/disk/util answers on Free (D05) if you also want the disk figure.
  • Verify a fresh project’s disk with GET /config/disk before relying on the documented baseline: Free started at 2 GB, not 1 GB (D05).
  • Raise IOPS on a Micro via the API only if you accept the bill: the POST was accepted and applied on Micro, and IOPS billing starts regardless of the dashboard’s Large-only text (D08). Whether IO throughput improved was not measured; D08 verified the config stuck.
  • Sizing cues: CPU utilisation + Disk IO % consumed (the burst-budget drain metric: >0 means past baseline). Over it -> upgrade.1 (docs)
  • Autoscale settings: cannot be observed via API; pin their intended state in IaC and audit the dashboard manually (D04, D07).

Not measured: paid-plan read-only at 95% disk; autoscale firing on any plan (D05 saw it not fire on Free); resize windows above Large or from a non-local vantage; whether the D09 REST gaps are per-client or per-vantage; the disk quota’s determinism (D03 varied run to run).

Doc claimRuntime measuredSeverity
read-only at 500 MB database (Free)read-only at ~726 MB, reads survivedocs stale
4 modifications / 24 h429 once/4h, nondeterministicdocs text differs, quota exists
Free disk starts 1 GBstarted 2 GBdocs understate
Large-only for IOPS/throughputaccepted + applied on MicroUI-only gate
autoscale config via APIverbs 404; GET emptysurface gap

Each measured row above comes from the supabase-lab pvlab harness, module ids D01-D09 under experiments/compute-disk, 2026-08-19, and re-runs are driven from the experiment’s probe scripts - the full run log is RUNLOG.md (the top-level consolidated reference also lives at the repo root: COMPUTE-DISK.md).

  • Settle seconds are measured from PATCH -> ACTIVE_HEALTHY status flip. Treat them as a floor; longer providers and disks stretch it.
  • contiguous-outage values in the resize table are the MAX visible gap across sampled clients - percent-ok inside a window can dip below that without creating an officially long gap.
  • Disk quota behavior varied run to run (bursts accepted, then reject); treat it as volatile, not a number to schedule against.

Measured claims map to module ids D01-D09 in the experiment; the documented and not-run rows rest on the cited pages only.

ClaimStatusHow it was checked
Per-size pg floors: Micro max_connections 60, wal senders 10, rep slots 10; Small 90 / 10 / 10measuredD01 - pg_settings read on a Pro org, resize to Small, re-read
Disk decrease refused (HTTP 400); increase accepted (HTTP 201)measuredD02 - attribute mutations on a fresh Pro project
Modification quota: 429 “once per four hours”; a 5-mod burst accepted in one runmeasuredD03 - serial +1 GB increases until one rejected
Autoscale on a Pro org: GET empty shape, PUT/POST/PATCH 404measuredD04 - verb probes against the autoscale endpoint
Free-org baseline disk 2 GB (docs: 1 GB); no growth at 90%+ through a fillmeasuredD05 - continuous fill on a Free project
Free read-only at ~726 MB database size (docs: 500 MB); reads kept answering; TRUNCATE rejected, DELETE required for recoverymeasuredD06 - write rejection, endpoint SELECT, and recovery in the same fill run
Autoscale gap identical on a Team orgmeasuredD07 - the same verb probes as D04
IOPS/throughput raise accepted and applied on Micro; the Large gate is UI-onlymeasuredD08 - config/disk POST, verified by follow-up GET
Resize settle 105/61/61/73 s; max contiguous outages 1.0/17.0/0/0 s; Auth 0 smeasuredD09 - REST and Auth sampled every 250 ms across the sequence
Nano rejected on a paid org; Free-org wake ~162-204 smeasuredinstance-sizing I01 (create + PATCH + catalogue); I04 (figure in the lab’s AGENTS.md, no RUNLOG entry)
Legacy free-era paused project on a Pro org: wake ~30 min, then 400 Project is not free-tier on pausemeasuredinstance-sizing I03, 2026-08-18
platform-plan org creates Nano by default (224 MB shared_buffers), and it can pausemeasured elsewheresfp-platforms S01 via the instance-sizing addendum, 2026-08-24/25
Per-size price, IO ceiling, and pg ceiling tables, incl. 24XL/48XL at 3,750 / 5,000 MB/s baselinedocumentednot run; cited to the Compute and Disk page
Disk autoscale defaults: 90% trigger, 50% growth, 1 GB minimum, 8 GB maximumdocumentednot run; cited to the Database Size page
Paid-plan read-only at 95% disk utilnot runcited to the Database Size page; not run here
  1. Supabase, “Compute and Disk,” Supabase Docs. https://supabase.com/docs/guides/platform/compute-and-disk 2 3 4 5 6 7 8 9 10

  2. supabase-lab, “Platform-downtime experiment,” supabase-lab runlog. https://github.com/erfianugrah/supabase-lab/blob/c1894cc/experiments/platform-downtime/RUNLOG.md

  3. Supabase, “Cost Control - Spend Cap,” Supabase Docs. https://supabase.com/docs/guides/platform/cost-control 2 3 4

  4. Supabase, “Database Size,” Supabase Docs. https://supabase.com/docs/guides/platform/database-size 2 3 4 5 6 7 8 9