Supabase egress: what counts, what it costs, how to cut it

By the SupaHost team · Updated 11 November 2026 · 7 min read · View as Markdown

Supabase egress is the data your project sends out to clients: API responses, file downloads, Realtime messages, Edge Function responses and Auth traffic. On the Pro plan you get 250 GB of uncached and 250 GB of cached egress per month, then pay $0.09 or $0.03 per GB (November 2026). Most egress bills come from a few habits, mainly large images and select * queries, and they are usually easy to fix.

What counts as egress

Supabase's egress docs define egress as network data transmitted from Supabase to a connected client. Every service draws from the same quota:

Source What sends data out
Database (Data API) Rows returned by PostgREST queries
Shared pooler Query results through the Supavisor pooler
Storage File downloads and public file URLs
Realtime Messages pushed to subscribed clients
Edge Functions Function responses
Auth Sign-in, sign-out and user management responses
Log drains Logs pushed to your drain

Uploads go into Supabase, so they are not egress. Downloads of those same files are.

Cached vs uncached egress

Supabase meters two kinds of egress separately, each with its own quota and price:

  • Cached egress is served from Supabase's CDN on a cache hit. In practice it comes mostly from Storage files served through the Smart CDN.
  • Uncached egress is everything else: database responses, Realtime, functions, Auth, and Storage requests that miss the cache.
Plan Uncached included Cached included Overage (uncached / cached)
Free 5 GB 5 GB Not billed; you're notified and a grace period starts
Pro 250 GB 250 GB $0.09 / $0.03 per GB

The quota belongs to your organization, not each project, so all your projects share the same 250 GB. Cached egress is a third of the price, which is why getting files cached is the single best lever for Storage-heavy apps.

What usually drives egress

Storage downloads

Images are the most common cause. A 4 MB photo straight from a phone camera, shown as a 200-pixel avatar, costs the same egress as if you displayed it full size. Multiply by every page view and it adds up quickly.

API payloads

select * on a table with a large jsonb or text column sends that column on every request, even if the UI never shows it. Lists without pagination, and screens that refetch the same data on every render or poll on a timer, have the same effect.

Realtime

With Postgres Changes, each change is sent to every subscriber whose filter matches. A 2 KB row update sent to 500 connected clients is about 1 MB of egress for one change. Busy tables with many listeners grow fast.

A quick estimate

Images:  10,000 daily users × 2 MB of images per day × 30 days  ≈ 600 GB
API:     10,000 daily users × 20 requests × 25 KB × 30 days     ≈ 150 GB

Halve the image sizes and select fewer columns and this app drops from about 750 GB to under 400 GB a month.

How to reduce Supabase egress

Select only the columns you need

// Sends every column, including large ones
const { data } = await supabase.from('posts').select('*')

// Sends only what the list view shows
const { data } = await supabase
  .from('posts')
  .select('id, title, created_at, author:profiles(username)')

Leave big jsonb and text columns out of list queries and fetch them on the detail page.

Paginate, and count without fetching

// 20 rows per page
const { data } = await supabase
  .from('posts')
  .select('id, title')
  .order('created_at', { ascending: false })
  .range(0, 19)

// Row count only, no rows returned
const { count } = await supabase
  .from('posts')
  .select('*', { count: 'exact', head: true })

Don't return rows you just wrote

In supabase-js v2, insert, update and upsert return no rows unless you chain .select(). Only add it when you need the result, and then select specific columns.

Shrink images before they are stored

Resize and compress images on the client or in a function before upload, and generate separate thumbnail sizes for lists and avatars. Set a maximum file size on each bucket so oversized files never get in. On Supabase Cloud, image transformations can resize on the fly (a paid feature with its own quota).

Set long cache headers on files

await supabase.storage
  .from('avatars')
  .upload(`${userId}/avatar-256.webp`, file, {
    cacheControl: '31536000', // one year, in seconds
    upsert: false,
  })

Long cache lifetimes let browsers reuse files instead of downloading them again. Use a new file name when the content changes, so caches never serve a stale version. Supabase's Storage scaling guide covers this along with the Smart CDN.

Cache on the client

Use a data-fetching library such as TanStack Query or SWR with a sensible stale time, so navigating back and forth does not refetch everything. Replace polling with Realtime where the data changes rarely, or poll less often.

Keep Realtime messages small

supabase
  .channel('room-42')
  .on(
    'postgres_changes',
    { event: 'INSERT', schema: 'public', table: 'messages', filter: 'room_id=eq.42' },
    (payload) => addMessage(payload.new)
  )
  .subscribe()

Filter subscriptions to the rows a client actually needs, unsubscribe when a screen is closed, and for high-traffic events use Broadcast with a small payload (an id and a type) instead of streaming full rows.

Compress where you control the response

If you return large JSON from Edge Functions or run your own proxy, make sure responses are gzip or brotli compressed. For log drains, Supabase recommends enabling GZIP if your provider supports it.

Put a CDN in front of public assets

For public files that many users download, a CDN serves repeat requests from its cache instead of your project. On Supabase this is the Smart CDN, billed as cheaper cached egress.

Egress allowances: Supabase Pro vs SupaHost

SupaHost runs open-source Supabase on a VM dedicated to your account, with one egress allowance shared by all projects on the instance.

Plan (November 2026) Egress included per month Overage
Supabase Pro ($25, one Micro project) 250 GB uncached + 250 GB cached $0.09 / $0.03 per GB
SupaHost Builder ($25) 250 GB $0.12/GB, or $12 per extra 100 GB
SupaHost Pro ($49) 500 GB $0.12/GB, or $12 per extra 100 GB
SupaHost Business ($99) 1 TB $0.12/GB, or $12 per extra 100 GB

Be clear about the trade-off. SupaHost's per-GB overage is higher than Supabase's uncached rate, and SupaHost has no image transformations. If you serve lots of images and lean on the Smart CDN's cheaper cached egress and on-the-fly resizing, Supabase Cloud is likely the better fit. SupaHost's larger allowances help when you run several projects whose combined traffic would otherwise need extra compute and overages on Supabase, since it doesn't charge per MAU, Realtime connection or function invocation.

Example for 800 GB of uncached egress a month:

Included Extra GB Egress cost
Supabase Pro 250 GB 550 $49.50
SupaHost Pro 500 GB 300 $36
SupaHost Business 1 TB 0 $0

To compare a full bill, not just egress, use the Supabase pricing calculator or the savings calculator on /migrate/supabase-cloud. For the rest of the Supabase price list, see Supabase pricing explained.

FAQ

What is egress in Supabase?

Egress is the data your Supabase project sends to clients. It includes database query results, Storage downloads, Realtime messages, Edge Function responses, Auth responses and log drains, all counted against one quota.

How much egress does Supabase Pro include?

Pro includes 250 GB of uncached and 250 GB of cached egress per month, shared across your organization. Beyond that, uncached egress costs $0.09 per GB and cached egress $0.03 per GB (November 2026).

What is the difference between cached and uncached egress?

Cached egress is served from Supabase's CDN when a file is already in its cache, usually Storage files. Uncached egress is everything served directly by your project, such as API responses and Realtime messages. They have separate quotas and cached egress is cheaper.

Why is my Supabase egress so high?

The usual causes are large unresized images, select * queries that return big columns, lists without pagination, frequent refetching or polling, and Realtime changes sent to many subscribers. Your usage page shows egress per service, which tells you where to look first.

Do file uploads count as egress?

No. Uploads are data coming into Supabase. Every download of the uploaded file does count, including downloads through public URLs.

Can I reduce egress I have already used?

No. Egress is counted when data is sent, so optimizations only reduce future usage. Fix the biggest source first, usually Storage images or wide API queries, and check the usage page after a few days.

Running several Supabase projects? SupaHost gives you your own server with the open-source Supabase stack and 5 to 30 projects for one monthly price. See plans or compare costs.