TL;DR
- Supabase free plan: 5GB egress/month
- My project: 10.26GB (205% over limit)
- Root cause: 5-second polling ×
select('*')on a table with a 200,000-char text column - Fix: generated column flag + select column restriction + visibilitychange polling stop
What happened
My KOBO project (issue-finder) had a collection-queue-form component polling if_jobs every 5 seconds via select('*'). The table includes raw_input_text (up to 200K chars). Through Vercel Functions, every poll was shipping that full column downstream.
5s interval × 200,000 chars × hours of operation = GB gone
Noticed when I checked the Supabase dashboard on 2026-05-31.
Fix 1: Generated column as boolean flag
If I only need to know whether raw input exists, I don't need to ship the text:
ALTER TABLE if_jobs
ADD COLUMN has_raw_input boolean
GENERATED ALWAYS AS (raw_input_text IS NOT NULL) STORED;
Fix 2: Narrow the select
// Before
const { data } = await supabase.from('if_jobs').select('*')
// After — list view only needs lightweight columns
const { data } = await supabase
.from('if_jobs')
.select('id, status, has_raw_input, created_at, updated_at')
Fix 3: Slow down polling + stop on hidden tab
useEffect(() => {
let interval: ReturnType<typeof setInterval> | null = null
const start = () => { interval = setInterval(fetch, 30_000) } // 5s → 30s
const stop = () => { if (interval) clearInterval(interval) }
document.addEventListener('visibilitychange', () =>
document.hidden ? stop() : start()
)
start()
return stop
}, [])
When does this happen to you?
-
select('*')on a table with large text/JSON columns - Polling interval ≤ 10s
- Serverless function proxy (Vercel, etc.) — egress counted on every hop
Full writeup (Japanese): https://masatoman.net/articles/supabase-egress-overage-free-plan-2026
Top comments (1)
Nice catch chasing the egress bill down to the actual column, that's the kind of bug that only shows up once you're already over the limit. Since if_jobs holds raw_input_text per job, is that table scoped to the owning user through RLS, or does the fetch happen server-side where that doesn't come into play?