Demo, all content is generated
Question

Database size is 380 MB but I only have a few thousand rows?

Solved · 612 views · asked by fin_ops · edited

Expense tracker, about 40 users, maybe 6000 expenses total. The dashboard says database size 380 MB and I got a warning about the 500 MB free limit. A few thousand rows can't be 380 MB, can it? Is Supabase counting something else?

What I’ve tried

Deleted old test users and their data, size didn't go down at all. Asked ChatGPT, it said to run VACUUM, which ran but nothing changed.

Comment
Does anything in the app store files or images? Receipts maybe? postgres_pete · edited

3 answers

Marked as helpful by the asker
postgres_pete · edited

Find what's big first, don't guess:

select relname, pg_size_pretty(pg_total_relation_size(relid)) as size
from pg_catalog.pg_statio_user_tables
order by pg_total_relation_size(relid) desc
limit 10;

My bet for an expense tracker: receipt photos stored as base64 text in a table column. That's the usual way ChatGPT "saves an image" when nobody tells it about Storage. Move them to a Storage bucket and keep only the path in the table.

On the delete not helping: plain VACUUM marks space as reusable but doesn't give it back to the disk. VACUUM FULL table_name rewrites the table and shrinks it, but locks the table while it runs, so do it at a quiet moment.

Comment
receipts table: 341 MB. Base64 photos, exactly like you said. Moved them to a bucket, ran VACUUM FULL, database is 31 MB now. fin_ops · edited
From 380 to 31, lovely. Storage has its own quota, so that's space well moved. postgres_pete · edited
hannah_reyes · edited

Other usual suspects for next time: cron.job_run_details and net._http_response grow forever if you use pg_cron or pg_net. Schedule a cleanup job that deletes rows older than a week.

Comment
job_run_details was 12 MB already, added a cleanup job. fin_ops · edited
jb_supa · edited

Late, but: the Storage bucket should get a policy so users only read their own receipts. Easy to forget when moving files out of a table that already had RLS.

Comment