Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.
PrivacyMedium

Implement a user-facing data deletion mechanism

Provide users with a clear way to request deletion of their personal data, fulfilling GDPR Article 17 (right to erasure / right to be forgotten).

Utilities
Quick take
Typical fix time 60 min
  • Provide a visible "Delete my account / data" option in account settings
  • Clear all client-side storage: localStorage, sessionStorage, IndexedDB, and cookies
  • Send a deletion request to the server and confirm receipt to the user
  • Complete deletion within 30 days as required by GDPR Article 17
Why it matters: GDPR Article 17 gives EU residents the right to have their personal data erased when it is no longer necessary for the purpose it was collected, or when they withdraw consent. Failing to honour this right can result in regulatory fines of up to €20 million or 4% of global annual turnover. Providing a clear deletion flow also builds trust with users who value control over their data.

Rule Details

The right to erasure (often called the "right to be forgotten") requires controllers to delete a user's personal data when requested, unless a legal ground for continued processing exists. For frontend applications this has two dimensions: clearing all client-side storage, and triggering deletion on the server.

Code Example

The deletion option must be discoverable. Place it in account settings under a clearly labelled section such as "Privacy" or "Your data". Use a two-step confirmation pattern to prevent accidental deletions:

// DeletionRequestButton.tsx
import { useState } from 'react';
import { clearUserData } from '@/lib/privacy';
 
type DeletionState = 'idle' | 'confirming' | 'pending' | 'done' | 'error';
 
export function DeletionRequestButton() {
  const [state, setState] = useState<DeletionState>('idle');
 
  async function handleConfirm() {
    setState('pending');
    try {
      // 1. Clear all client-side storage immediately
      clearUserData();
 
      // 2. Send deletion request to the server
      const response = await fetch('/api/account/delete', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
      });
 
      if (!response.ok) throw new Error('Server deletion request failed');
 
      setState('done');
    } catch {
      setState('error');
    }
  }
 
  if (state === 'done') {
    return (
      <p role="status">
        Your deletion request has been received. Your data will be removed
        within 30 days. You have been signed out.
      </p>
    );
  }
 
  if (state === 'confirming') {
    return (
      <div role="alertdialog" aria-labelledby="delete-confirm-title">
        <h2 id="delete-confirm-title">Delete your account and all data?</h2>
        <p>This action cannot be undone. You will be signed out immediately.</p>
        <button onClick={handleConfirm} disabled={state === 'pending'}>
          {state === 'pending' ? 'Deleting…' : 'Yes, delete my data'}
        </button>
        <button onClick={() => setState('idle')}>Cancel</button>
      </div>
    );
  }
 
  return (
    <button onClick={() => setState('confirming')}>
      Delete my account and data
    </button>
  );
}

Why It Matters

GDPR Article 17 gives EU residents the right to have their personal data erased when it is no longer necessary for the purpose it was collected, or when they withdraw consent. Failing to honour this right can result in regulatory fines of up to €20 million or 4% of global annual turnover. Providing a clear deletion flow also builds trust with users who value control over their data.

What Must Be Deleted

A compliant deletion covers every location where personal data may be stored:

Storage LocationAPI to clear
localStoragelocalStorage.clear() or per-key removeItem
sessionStoragesessionStorage.clear()
IndexedDBindexedDB.deleteDatabase(name)
CookiesSet each cookie's Max-Age=0; expires=Thu, 01 Jan 1970
Service Worker cachescaches.delete(cacheName)
Server-side dataDELETE / POST request to your deletion API

Clearing All Client-Side Storage

The clearUserData() helper should be a single function that handles every client-side storage mechanism. Centralising this logic makes it easy to audit and extend:

// lib/privacy.ts
 
/**
 * Removes all personal data from client-side storage.
 * Call this immediately when a deletion request is confirmed — do not wait
 * for the server response, as the user has already expressed intent to delete.
 */
export async function clearUserData(): Promise<void> {
  // 1. localStorage
  localStorage.clear();
 
  // 2. sessionStorage
  sessionStorage.clear();
 
  // 3. IndexedDB — delete every database the application has created
  const databases = await indexedDB.databases();
  await Promise.all(
    databases.map((db) => {
      if (!db.name) return Promise.resolve();
      return new Promise<void>((resolve, reject) => {
        const req = indexedDB.deleteDatabase(db.name!);
        req.onsuccess = () => resolve();
        req.onerror = () => reject(req.error);
      });
    })
  );
 
  // 4. Cookies — clear known application cookies
  const cookiesToDelete = ['session', 'refresh_token', 'user_prefs', '__stripe_mid'];
  for (const name of cookiesToDelete) {
    document.cookie = `${name}=; Max-Age=0; path=/; SameSite=Lax`;
  }
 
  // 5. Cache Storage (Service Worker caches)
  if ('caches' in window) {
    const cacheNames = await caches.keys();
    await Promise.all(cacheNames.map((name) => caches.delete(name)));
  }
}
Don't wait to clear client-side data

Clear client-side storage before awaiting the server response. If the network request fails, the user's local data is still gone — which is the correct behaviour. Retrying the server call is separate from the local clearance.

Server-Side Deletion API

The server must accept deletion requests and schedule them within the 30-day GDPR window. A typical REST implementation:

// app/api/account/delete/route.ts (Next.js App Router)
import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
 
export async function POST() {
  const session = await getServerSession();
  if (!session?.user?.id) {
    return NextResponse.json({ error: 'Unauthenticated' }, { status: 401 });
  }
 
  // Queue deletion — process asynchronously within 30 days
  await scheduleDeletion({
    userId: session.user.id,
    requestedAt: new Date().toISOString(),
    // GDPR deadline: 30 calendar days from request
    deadline: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
  });
 
  // Send confirmation email to the address on record before it is deleted
  await sendDeletionConfirmationEmail(session.user.email);
 
  return NextResponse.json({ received: true });
}

Confirmation and Timeline Communication

After a deletion request is submitted, inform the user:

  • That the request has been received
  • The deadline by which data will be removed (e.g. "within 30 days")
  • That they have been signed out of all devices
  • A reference number for their records (if your system supports it)
Third-party data processors

Your application likely passes personal data to third-party processors (analytics, CRM, email tools). Deletion requests must also be forwarded to these processors. Check each processor's API for a deletion endpoint and include those calls in your deletion workflow.

Standards

  • Use these references as the standard for the legal or product-facing privacy behavior that users actually experience.
  • Check the implementation against GDPR Article 17 — Right to erasure before treating the rule as satisfied.
  • Check the implementation against ICO: Right to erasure before treating the rule as satisfied.

Support Notes

  • Privacy features can differ by browser storage, cookie, and embed behavior, so verify the user-facing outcome in the supported environments rather than relying only on server logic.
  • Document any fallback or platform-specific limitation when a privacy control is interpreted differently across browsers.

Verification

Automated Checks

  • Sign in as a test user, then trigger the deletion flow. Confirm localStorage, sessionStorage, and cookies are empty in DevTools Application panel immediately after confirmation.
  • Open the IndexedDB panel in DevTools and verify all databases are removed.

Manual Checks

  • Check the server receives a deletion request by inspecting the Network tab — the POST to /api/account/delete should return 200.
  • Verify a confirmation message is displayed to the user with a reference to the 30-day timeline.

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Check whether this application provides a user-facing data deletion mechanism that clears all client-side storage and triggers a server-side deletion request.

Fix

Auto-fix issues

Implement a data deletion flow that clears localStorage, sessionStorage, IndexedDB, and cookies, then sends a deletion request to the server and shows confirmation to the user.

Explain

Learn more

Explain GDPR Article 17 (right to erasure) and what a compliant data deletion flow must cover, including both client-side and server-side data.

Review

Code review

Review account settings, privacy pages, and API routes for a data deletion endpoint. Flag missing client-side storage clearance, absent confirmation UI, or missing server-side deletion calls.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

Lighthouse Privacy Auditsdeveloper.chrome.comTool

Rules that often go hand-in-hand with this one.

Collect only the minimum personal data necessary

Limit data collection to only what is strictly required for the stated purpose, in line with GDPR Article 5(1)(c) data minimisation principles.

Privacy
Implement Google Consent Mode v2

Adjust Google Tag behavior based on user consent to comply with privacy regulations and maintain data insights.

Performance
Link to your privacy policy in the footer

Websites that collect any personal data must publish a privacy policy and link to it prominently — this is a legal requirement under GDPR, CCPA, and most other privacy regulations.

Privacy
Avoid third-party cookies

Third-party cookies set by external domains track users across sites without their knowledge. Modern browsers are phasing them out, and regulations like GDPR and CCPA require consent before setting them.

Privacy

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385