How to Delete a User Properly with Supabase and Next.js
Deleting a user is not just removing a row from auth.users. You also need to think about relations, history, derived data, and compliance.
Deleting a user account seems simple. In practice, it's rarely just "delete user". Between user Auth, linked data, storage, sessions and product obligations, the subject must be handled properly.
With Supabase and Next.js, the right goal is not just to delete. The correct goal is to delete without leaving any inconsistency.
What many do wrong
The classic shortcut is:
- call a deletion on the user
- think that everything else will follow
The problem is that an account can have much more than its line in auth.users:
- profiles
- messages
- projects
- files in Storage
- business relationships
- useful traces to keep or anonymize
If you don't map this, you remove an identity, but you leave a bunch of orphaned data.
What Supabase says
The Supabase documentation is clear on two useful points:
- admin deletion of a user requires
service_role - you cannot delete a user if he is the owner of objects in Supabase Storage
You must therefore think of deletion as a server flow and not as a simple front-end action.
Deletion, anonymization or archiving
Before writing code, you must choose the right product action.
Depending on the context, you may need:
- total deletion: account and associated data erased
- anonymization: business data remains, but without direct identity
- archiving: the account is no longer active, but the data is retained for a legal or operational reason
If you sell to businesses, this choice often has a legal, support and reporting impact. It must therefore be defined before coding.
The right server flow
In a Next.js project, the cleanest schema looks like this:
- user requests deletion
- a server route verifies its identity and rights
- the server draws up the list of data to be processed
- Storage files are deleted or reassigned if necessary
- business data is deleted or anonymized
- Auth user is deleted last
This last point is important. If you remove the Auth user too early, you sometimes lose flow consistency and useful context to complete the cleanup.
An example of sequence
In a typical customer portal, a clean delete might look like this:
- deletion or reassignment of Storage objects
- deletion of child lines which depend on the account
- possible anonymization of histories to be preserved
- profile deletion
- admin deletion of the Auth account
Supabase offers the deletion operation via the JavaScript admin API:
await supabase.auth.admin.deleteUser(userId)
This operation must remain on the server side.
The session trap
Supabase also reminds that a JWT can remain valid until its expiration. In practice, this means that after deletion, a session may not disappear instantly from the browser's point of view.
It is therefore necessary to provide clear experience:
- disable app side access
- properly redirect the user
- avoid ambiguous screens or incomprehensible errors
Security and user experience come together here.
The special case of Storage
This is a point that we often forget.
If the user has Storage objects, Supabase can refuse its deletion as long as these objects still exist. It is therefore necessary:
- know the bucket
- know the owner logic
- delete or reassign files before
If you skip this step, the deletion fails and the team often thinks "Supabase bug", even though the behavior is documented.
A mini checklist before plugging in the button
Before adding a “Delete my account” button, check:
- which tables reference the user
- which Storage files belong to it
- what data should be deleted
- what data should be anonymized
- what experience the user will see after the request
This checklist seems simple, but it avoids a lot of debt and support stress.
What to remember
Deleting a user account properly with Supabase and Next.js is not just about calling an admin method. It's defining a clean server flow, processing related data, anticipating Storage, then handling user exit with clarity.
Good code starts with a good product decision: what really needs to go, what needs to stay, and who bears responsibility for cleaning it up.
Official sources
Keep reading on the same topic
These links reinforce the blog's topical cluster and help search engines understand the article's primary subject.
