When your Supabase projects start to pile up, three questions come fast: what belongs to the organization and what to the project, how do I move a project, and which ones are dead? I tried all three on a throwaway setup and built a small board that shows the answer on one screen. Everything here is from my run on 2026-10-27, and prices and rules change.
How this was made: I wrote this with Claude's help: it drafted, and I ran every step, edited the text, and checked the results. The mistakes are mine. This is a personal learning project, not an official guide, and I don't work for Supabase.
The non-technical version of the idea (company and offices): https://medium.com/p/f19c78f2ba25
The code: https://github.com/tomozilla/project-inventory-en-demo
The Billing FAQ says it plainly: an organization holds many projects; each project is a dedicated instance with its own Storage, Auth, Functions and Realtime; each organization has one subscription plan; and project add-ons (compute, PITR, custom domains) are set per project but billed through the organization.
My own cheat sheet:
| Organization | Project | |
|---|---|---|
| Plan and billing | here | (uses the organization's) |
| Members and roles | here | covered by the organization's |
| SSO, audit logs | here | |
| Database, Auth, Storage, Functions | here | |
| Compute size, backups, PITR | here | |
| API keys, URL | here |
Two consequences from the docs: a paid plan applies to every project in that organization, and you cannot mix free and paid projects inside one organization.
My free organization has two projects. One is d. The pricing page says free projects after a week of inactivity, so I assume that is why. I did not confirm the reason on screen.
Settings like SSO and audit logs live on the organization side, not in a project.
I decide by asking what must never be mixed.
One docs detail surprised me: the limit of two active free projects is counted across every Owner and Admin of the organization. If another admin already used their allowance, you can't launch another free project there. The docs suggest creating another free organization or changing that member's role. I am the only member of my organization, so I did not reproduce this.
Create the target organization at /dashboard/new. Check that the plan says Free - $0/month.
Then open the project's Project Settings -> General and scroll to Transfer project.
The dialog warns about three things: possible downtime when moving from paid to free, permission changes depending on your role in the target, and lost features (for example image transformations) on a smaller plan.
I picked the new organization and confirmed. It took a few seconds, and the project reference stayed the same.
Then I moved it back the same way and deleted the temporary organization (Organization Settings -> General -> Delete organization). Deleting asks you to type the organization's slug. I checked the page title first, because it is permanent.
What the docs say, which I did not test:
You don't have to open every project. The CLI lists them (read-only):
supabase projects list --output json
Each project comes back with ref, name, organization_id, region, created_at and status. In my run a d project showed "status": "INACTIVE".
Two limits matter:
Before deleting anything, ask the owner. d projects are not charged for compute according to the docs, so there is no rush.
I turned that into a page: paste the CLI output, and see projects grouped by organization.
It is a static page. No server, no project, no access token, and what you paste stays in the browser.
Because the output has no plan, you pick it per organization. The estimate counts running projects only:
monthly = Math.max(0, active * 10 - 10); // Micro $10 per running project, minus the $10 included
monthly += plan === "pro" ? 25 : 599; // plan fee
Run it from the repository root, because the sample button reads ../sample/:
python3 -m http.server 8000 # then open http://localhost:8000/app/
node app/test.js # 13 checks
supabase projects list --output json | pbcopy # your own data (macOS)
With the sample, I set organization 1 to free and organization 2 to pro:
I also checked that the parser reads my real CLI output (3 projects in 2 organizations). I looked at the counts only and kept the names out of this article and the repo.
I decided the page should never go blank silently. A broken paste shows the reason in red, and rows missing ref, name, organization_id, status or created_at are skipped with a count, not dropped quietly.
The page said "1 projects", and the per-organization tables had different column widths. Both fixed.
Ideas I haven't tried: a separate file that maps organization ids to names and owners, a diff against the last inventory so only new or newly d projects show up, and never letting the tool decide that something is safe to delete.
Next in this series: how to read your bill.