Supabase Pricing: What Drives the Bill
By Aakash Verma · · 7 min read
The Supabase pricing page says Pro is $25 a month, and that number is true. It's also the least interesting number on your invoice once you have real users. The bill is really five things stacked on top of each other: the plan fee, compute for every project, usage over the included quotas, add-ons you switched on at some point, and disk that grew and never came back down.
If you hand me a Supabase invoice, this is the order I check them in, because it's roughly the order of how much money they move. All prices are from supabase.com/pricing and the billing docs as of October 2026.
Compute is per project, and the credit covers one
Every Supabase project is its own Postgres server, and every server is billed by the hour. Pro includes $10 a month of compute credit, which pays for exactly one Micro instance (1 GB RAM, $0.01344 an hour, about $10 a month). The credit is per organization, not per project.
So the moment you add a staging project, you're paying for it. Supabase's own billing docs have the example: a Pro org with three projects on Small compute is $25 + 3 × $15 − $10 = $60 a month, not $25. Add a "test" project someone made in March and forgot, and it keeps billing every hour of every day. Paid projects don't pause for inactivity the way free ones do.
The rest of the compute ladder, monthly: Small $15 (2 GB), Medium $60 (4 GB), Large $110 (2 dedicated vCPUs, 8 GB), XL $210, 2XL $410, and it keeps going to 16XL at $3,730. Medium to Large is where the jump hurts, and it's the step people take to get more database connections. Don't. If your serverless functions are running out of connections, point them at the Supavisor pooler in transaction mode (port 6543). A Small instance accepts 400 pooler clients and Medium 600, without paying for a bigger box.
One sneaky one: if you upgraded from Free to Pro, your old project may still be on Nano compute. On a paid plan Nano is billed at the Micro price, so you're paying for Micro and getting Nano. It doesn't move automatically because a resize means a couple of minutes of downtime. Do it yourself in the project's compute settings.
And dev projects don't need to live in the paid org. A separate Free organization gives you two active free projects that cost nothing and pause after a week of inactivity, which is exactly what you want from a staging database nobody touches between releases.
The spend cap is not a budget
People turn on the spend cap and stop worrying. Read what it actually covers.
It exists only on Pro (Team and Enterprise don't have it). It's an on/off switch, not a dollar limit, so there's no way to say "stop me at $80". With it on, usage items can't go past the plan quota: egress, disk size, MAU, storage size, edge function invocations, realtime messages and connections, image transformations, log ingest. Instead of billing you, Supabase restricts the project. Uploads fail, API calls start returning errors, and a full disk goes read-only.
What it doesn't cover is the stuff that's already big: compute hours, branching compute, read replicas, point-in-time recovery, the IPv4 add-on, custom domains, log drains, and any extra IOPS or throughput you provisioned. Those keep billing whatever the switch says. If your bill jumped and the cap was on, the jump is almost certainly in that list.
Egress is the line item that surprises people
Pro includes 250 GB of uncached egress and another 250 GB of cached egress a month. Past that it's $0.09 per GB uncached and $0.03 per GB cached. Egress means everything leaving Supabase: Data API responses, storage downloads, edge function responses, realtime pushes, the pooler. One quota for all of it, pooled across the projects in the org.
The two usual causes are boring:
select('*') on tables that grew. A list screen that loads 50 rows with every column, including the description text and the metadata JSON nobody displays, sends a lot more bytes than the 4 columns it renders. Multiply by every page view. Selecting the columns you use (.select('id, title, price')) is the cheapest optimisation there is.
Images straight out of storage. If public files are uploaded without a long cacheControl, every view can go back to the origin and count as uncached egress at three times the cached price. Set cacheControl: '31536000' on uploads of files that never change, and consider putting your own CDN in front for heavy media. On-the-fly image transformations are their own meter too: 100 origin images included on Pro, then $5 per 1,000 origin images, billed in whole packages. For a product catalog that's fine. For user uploads at scale, I'd rather generate the two or three sizes I need once, at upload time.
Disk grows by itself and never shrinks
Pro includes 8 GB of database disk per project, then $0.125 per GB a month. On paid plans the disk autoscales: when it reaches 90% full, it grows by 50% (8 GB to 12, 12 to 18, capped at 200 GB per step), at most four times in a rolling 24 hours.
Then it stays that size. Deleting rows or dropping a table frees space inside Postgres, but the disk doesn't get smaller. So a one-off import that pushed you to 150 GB costs about (150 − 8) × $0.125 = $17.75 a month, forever, even after the data is gone. The ways back down are a Postgres version upgrade from the dashboard, which rebuilds the disk at 1.2 times the actual database size (8 GB minimum), or moving to a fresh project.
The import itself has a trap. If you load more than about 1.5 times your current database size in one go, the disk fills faster than autoscaling is allowed to react, hits 95%, and the database goes read-only (SQLSTATE 25006, read_only_sql_transaction). Your app starts failing writes in production. Expand the disk by hand before a big import, and put large files in storage instead of bytea columns.
Add-ons: the hourly charges you opted into once
Hourly charges that take one click to turn on and are easy to forget about.
Point-in-time recovery is $100 a month for 7 days of retention, $200 for 14, $400 for 28. Supabase's own example of a Pro org with one Small project and 7-day PITR comes to $130 a month. For a lot of apps, the daily backups Pro already includes (7 days) plus a nightly supabase db dump to your own bucket are enough. PITR earns its keep when losing an hour of writes would really cost you, and plenty of apps aren't there yet.
Branching is $0.01344 per branch per hour, roughly $10 a month each, and the compute credit doesn't apply to it. With the GitHub integration, a preview branch can be created for every pull request. Leave stale PRs open and you're running a small fleet of databases.
Read replicas bill their own compute plus disk from the first byte, sized at 1.25 times the primary's disk. They also copy the primary's add-ons, so an IPv4 add-on on the primary is billed again on every replica.
The IPv4 add-on is $4 a month per database, and most people buy it because their host can't do IPv6 direct connections. The pooler already works over IPv4 on every plan, at no cost. A custom domain is about $10 a month. Log drains are $60 a month per drain, plus $0.20 per million events, plus egress.
Realtime and MAU, briefly
Realtime is 5 million messages a month on Pro, then $2.50 per million, plus 500 peak connections included. postgres_changes sends a message to every subscriber for every change on the table, so subscribing a dashboard to a table that a background job updates every few seconds gets expensive quietly. Filter subscriptions (filter: 'org_id=eq.42') or use Broadcast for state that doesn't need to be a database row.
Monthly active users are 100,000 included, then $0.00325 each. A user counts once per billing cycle when they sign in, sign up or refresh a token. Anonymous sign-ins count too, which matters if bots can reach your sign-up flow. Supabase supports CAPTCHA (hCaptcha or Cloudflare Turnstile) on auth, and it's worth switching on before you need it.
Where to look
The organization's Usage page breaks everything down per project and per item, and the billing page shows the upcoming invoice before it's charged. Storage and disk are billed in GB-hours, so what you pay is your average over the month. Delete 50 GB halfway through a 30-day cycle and you pay for about 25 GB that month, then the full saving after.
If you go through all of this and the bill still doesn't make sense, send it to me. Cutting bills like this is what my free cloud cost optimization offer is for. I read the invoice, the usage page and the code that drives it, and you only pay out of what I actually save.
Introductory offer
Free cloud cost optimization. You only pay from what I save.
I cut your AWS, cloud, Supabase or Vercel bill for free and keep half of what I save for 6 months. Save nothing, pay nothing. Code, architecture and infrastructure.