← Blog
Technical4 min read7 July 2026

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.

PN
Paul Noorman
Founder, OurPlan
How to Delete a User Properly with Supabase and Next.js

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:

  1. user requests deletion
  2. a server route verifies its identity and rights
  3. the server draws up the list of data to be processed
  4. Storage files are deleted or reassigned if necessary
  5. business data is deleted or anonymized
  6. 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:

  1. which tables reference the user
  2. which Storage files belong to it
  3. what data should be deleted
  4. what data should be anonymized
  5. 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