# "Please delete all my data." Deleting the Stripe customer doesn't do it.

Here's the thing most small SaaS founders get wrong the first time someone writes "please delete my account and all my data": they open Stripe, click delete on the customer, drop the row from `users`, reply "done!" and move on.

Two problems with that. Stripe's own API reference says deleted customers "can still be retrieved through the API in order to be able to track their history." Deleting a customer removes the card details and stops new charges. It doesn't make the name and email disappear. And your `users` row was probably the smallest copy of that person you had.

This is a support ticket with a clock on it, so I think it's worth having the process written down before the first one shows up.

## The clock is one month, not "when I get to it"

If the person is in the EU or UK, GDPR Article 12(3) says you have to tell them what you did "without undue delay and in any event within one month of receipt of the request." You can extend by two more months for complex cases, but you have to tell them about the extension, with a reason, inside that first month.

Article 12(5) also says it's free. You can't charge for it unless the requests are "manifestly unfounded or excessive," and the burden of proving that is on you.

Even if you've never had a European user, I'd just run every deletion request on the one-month rule. One process is easier than three.

## Step 1: make sure it's really them

Deletion is permanent. A request from a random Gmail address saying "delete the account for ceo@theircompany.com" is a great way for someone to wipe a business's data.

Article 12(6) lets you ask for more information when you have "reasonable doubts" about identity. In practice for a tiny SaaS:

- If the request came from the account's login email, that's usually enough.
- If it came from anywhere else, reply to the login email on file and ask them to confirm from there. Don't act on the new address.
- If it's a team account, check the person is the owner, not just a member.

Ask only for what you need. Requesting a passport scan to delete a free account is overkill and creates a new pile of sensitive data you now have to delete.

This is the same trap as account takeover by support ticket. I wrote about that in [why "please change my login email" is the riskiest ticket you'll get](https://praneetbrar.hashnode.dev/change-login-email-support-request), and the same rule applies here: confirm from the old address, never from the reply.

## Step 2: list every place that person lives

This is the part that takes time the first time and five minutes after that. Make a checklist once and keep it in your repo. Mine would look roughly like this for a typical small product:

1. **Your database.** The `users` row, plus everything with a `user_id` on it: projects, comments, API keys, sessions, invites they sent, audit logs.
2. **File storage.** Avatars and uploads in S3, R2 or wherever. These are the ones people forget, because nothing in the database cascades to a bucket.
3. **Payments.** Stripe (or Paddle, Lemon Squeezy).
4. **Email.** Your transactional provider's logs and your newsletter or marketing list.
5. **Support tool.** The helpdesk or shared inbox with every past ticket.
6. **Product analytics and error tracking.** Anything where you called `identify()` with their email or ID.
7. **Spreadsheets and Notion.** The "early users" sheet everyone has.
8. **Backups.** Last, and handled differently (see below).

If your uploads are keyed by a random ID with no link back to the user, step 2 gets painful. I went through how I'd [structure file uploads in a small product](https://makerhunt.io/studio/how-to-handle-file-uploads-in-your-product?utm_source=hashnode&utm_medium=crosslink&utm_campaign=hashnode-delete-my-data) so the storage side stays manageable.

## Step 3: Stripe needs redaction, not just delete

Stripe has a separate feature for this. Their docs recommend [redaction jobs for consumer deletion requests](https://docs.stripe.com/privacy/redaction): you create a job with the customer ID, it validates every related object (payment intents, charges, invoices, payment methods), and then you run it. Personal fields get replaced with `[redacted]`.

Three things I'd want to know before running one:

- **It's irreversible.** Stripe says redacted transactions "are automatically lost in a dispute, and you can't refund them." So if they paid you last week, sort out any refund first.
- **Some things block it.** Open disputes have to be closed, unused payment intents cancelled, payment methods detached. Stripe also notes that fraud-flagged transactions can only be redacted after 90 days.
- **Redaction Jobs is in public preview** at the time I'm writing this, and you have to request access. If you don't have it yet, at minimum cancel the subscription, delete the customer, and tell the person honestly what Stripe keeps.

Stripe also says it may keep data it's legally required to keep after redaction. That's Stripe's obligation as a payment provider, not something you can delete for them.

## Step 4: decide what you're allowed to keep

The right to erasure isn't absolute. Article 17(3) lists exceptions, and two matter for a small SaaS:

- **A legal obligation.** If tax law says you keep invoices for a number of years, you keep the invoices. You don't keep their onboarding survey answers "just in case."
- **Legal claims.** If there's an open dispute or a fight about money, you can keep what you need for that.

Keep the minimum, and say so in your reply. "We've deleted your account and content. We're required to keep invoices for X years for tax purposes, which include your name and billing address" is a fine sentence. Silence is not.

## Step 5: backups, the honest version

You're not going to restore every nightly snapshot, strip one user and re-save it. The UK regulator, the ICO, says in its [guidance on the right to erasure](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/individual-rights/individual-rights/right-to-erasure/) that the key is to put backup data "beyond use": don't use it for anything, and let it be overwritten on your normal schedule.

Two things that make that work:

- Have an actual retention schedule. "Backups kept 30 days" is a real answer. "Backups kept forever because I never set it up" isn't.
- If you ever restore a backup, re-run your deletions on the restored data. Keep a small table of deleted user IDs and dates (no other personal data) so you can do that.

## Step 6: reply with what you did

The reply should be boring and specific. Something like:

> Hi, your account and everything tied to it (projects, uploads, support history, mailing list entry) has been deleted as of today. We keep invoices for tax reasons, which include your name and billing address. Our backups roll over every 30 days, so any copy there will be gone by [date]. If anything ever turns up, reply here and I'll deal with it.

Then log it: date received, date done, what was deleted, what was kept and why. If a regulator or the person ever asks, that log is your proof.

## The 30-minute version to do this week

If you have zero process today, I'd do just three things:

1. Write the step 2 checklist for your actual stack and put it in your repo.
2. Write one script or admin action that deletes a user across your database and storage, and test it on a fake account.
3. Check your backup retention and write the number down.

That covers most of it before the first request ever shows up.

One question I'm still going back and forth on: when a user asks you to delete their data, do you also remove their comments or posts that other people replied to, or anonymise them to "deleted user" so the thread still makes sense? I'd like to hear how other people handle that.

