User Data Export and Deletion Workflows for Small Apps

A Delete account button is only the start of a reliable deletion workflow. A user's information may also exist in uploaded files, search indexes, analytics, support tools, application logs, payment systems, and backups. An export can be just as difficult: a database dump may expose another person's information, credentials, or internal records along with the user's own data.

For a small application, the practical solution is to map where personal data goes, define what each kind of request means, and make the work trackable from identity verification through completion. This guide covers the engineering workflow. It is not legal advice; which laws apply, what must be provided, and what may be retained depend on your business, users, processing, and jurisdiction.

Export, access, and deletion are different requests

Do not treat every request for "my data" as a request to download every database row. The legal rights have different scopes.

Request European Union: GDPR California: CCPA, as amended
Access or know The right of access covers personal data being processed and related information. The controller generally has one month to respond; a complex request may be extended by up to two further months with notice during the first month. The right to know covers specified information about collection and use, including specific pieces of personal information in applicable cases. The California Privacy Protection Agency (CPPA) says businesses generally must acknowledge a delete, correct, or know request within 10 business days and respond within 45 calendar days; they can extend by another 45 days with notice.
Portability The separate right to data portability is narrower than access. It applies to data the person provided, when processing is automated and based on consent or contract; the person can receive it in a structured, commonly used, machine-readable format and, where technically feasible, transmit it to another controller. California's right to know has its own scope and delivery rules. Do not assume it is interchangeable with GDPR portability; check the current statute and regulations for the request and business involved.
Deletion or erasure The right to erasure has exceptions, including some legal obligations and legal claims. A request does not automatically require deleting every record in every situation. Consumers may request deletion, subject to statutory exceptions. The CPPA says covered businesses must also tell service providers to delete when required.

These are not universal deadlines or a complete statement of either law. The GDPR's territorial scope and the CCPA's business thresholds and definitions differ. The CCPA generally applies to qualifying for-profit businesses, not automatically to every app with a California user. Check the GDPR text, the CPPA's current CCPA FAQs, and the current California regulations before setting policy or promising a date.

Map the data before writing the endpoint

Create a short inventory that connects each user identifier to the stores and vendors where it appears. Start with the account ID, but include other identifiers such as email, organization ID, billing customer ID, or an external provider's user ID. A single user may have several records that are not joined by the same key.

Data location Examples What to decide
Primary application store Profile, preferences, projects, messages, uploaded files Which records belong only to this user, and which are shared with a team or another user?
Derived and replicated stores Search indexes, caches, data warehouse, generated reports How will changes be propagated, and how will stale copies expire?
Third-party services Payment processor, email provider, support desk, analytics Which party controls the data, what API or support process handles requests, and what does your contract require?
Logs and audit records Request metadata, error logs, security events What minimum evidence is useful, who can access it, and how long is it retained?
Backups Database snapshots, object-store versions, disaster-recovery copies When do copies expire, how are they protected, and how will a restore reapply completed deletions?

Keep the inventory practical: record the store, the identifiers used to find a person, the action required for export or deletion, the owner, and how completion is confirmed. Update it when you add a vendor or a new type of user content. If you collect less information in the first place, there will be less to search, export, secure, and remove. For analytics decisions, see our guide to privacy-friendly web analytics for small websites.

Build a request workflow with clear checkpoints

1. Accept and classify the request

Provide a clear contact route in your privacy notice and, where appropriate, an authenticated account setting. Record a request ID, received time, request type, and the account or organization involved. Classify requests separately as access, export/portability, deletion, or another correction or opt-out request; the action and response can differ.

An in-product button can automate an account-closure request, but it does not necessarily cover a formal access request or data held by a separate controller. Tell users what the button does and what it does not do. If someone asks for both an export and deletion, make the order explicit: verify the request, prepare and securely deliver the requested export, then run deletion where applicable.

2. Verify identity without collecting extra data

Use the signed-in account for an authenticated request when that is sufficient. For a request made by email or for a particularly sensitive export, use a proportionate verification step, such as a confirmation link to the address already on the account or a fresh sign-in. Do not send an archive to an address supplied only in the request.

Verification should reduce disclosure risk without turning into unnecessary identity collection. The GDPR allows a controller to request additional information when it has reasonable doubts about identity; the CCPA also allows verification for relevant requests. Avoid asking every user for a government ID by default. Document the verification method and result, not a copy of sensitive proof unless there is a specific justified need and retention plan.

3. Generate a scoped, readable export

Return the personal data and accompanying information required for the request, not a raw database backup. Use JSON for nested records and relationships, or CSV for simple tables. Include a short manifest that explains the files, fields, date range, and export timestamp. Use stable IDs to preserve relationships between records, and make dates and time zones clear.

Before delivery, check that the export:

  • Includes the correct account and the relevant data stores.
  • Excludes other users' content, secrets, passwords, authentication tokens, and unnecessary internal diagnostics.
  • Preserves useful relationships between records instead of returning disconnected rows.
  • Is delivered through an authenticated, access-controlled route. If you use a download link, make it unguessable, short-lived, and single-purpose.

Access and portability are not the same. Under GDPR, Article 15 access and Article 20 portability have different scopes; portability is not a right to every inferred record or every internal database field. California's right to know is a separate statutory right, with specific rules about what a covered business must disclose and how. Do not silently substitute one jurisdiction's export format for another's requirements.

4. Delete in stages and make retries safe

An asynchronous job is often easier to operate than deleting every record inside one web request. First block further sign-in or use if the user requested account closure. Then run a durable job that processes each mapped store, records its outcome, and can safely retry a failed step without duplicating side effects.

Keep deletion status separate for the primary database, uploaded files, indexes, caches, and vendors. Do not report completion while required work is still queued or has failed. If the account belongs to a team, define what happens to shared projects and comments; deleting one member should not unexpectedly erase data belonging to other users.

Some records may need to be retained for a legal obligation or another applicable exception. Do not invent a blanket "business records" exception. Have the responsible person determine the specific basis, limit access and use to that purpose, record the reason and review or deletion date, and explain the limitation to the requester as required. A retention exception is not permission to keep unrelated account data indefinitely.

5. Include processors, logs, and backups

For each service provider, record whether your app can delete the data through an API, dashboard, or support request. Send the appropriate instruction, capture the provider's result, and include the provider in your completion checklist. Under GDPR, processors assist controllers with data-subject requests, and a controller may have to communicate erasure to recipients in applicable cases. California deletion requests also have requirements involving service providers. Check your role and contract rather than assuming a vendor has deleted a record because your local row is gone.

Logs need special handling. Prefer a small audit record such as a request ID, timestamps, store outcomes, and an exception code over copying the user's data into the request log. Restrict access and set a retention period for those records too. The OWASP Logging Cheat Sheet recommends choosing log content based on purpose and risk rather than recording everything.

Backups are not a reason to ignore deletion. Document their retention period and access controls; let old copies expire under the planned rotation, and keep a deletion marker or equivalent process so a restore does not put already-deleted accounts back into service. A backup may not be immediately editable like a live database, but that does not make it an automatic legal exception. Set the backup policy with qualified advice for the laws and contracts that apply to your app. For the recovery side of that plan, see database backup and restore plans for small web apps.

6. Confirm completion and retain minimal evidence

Track each step with a status such as pending, complete, failed, or retained-under-exception. When the workflow finishes, tell the user what was completed and identify any relevant limitation in plain language. Keep only the request evidence you need to show what happened, restrict access to it, and give it its own deletion schedule.

For example, a small request ledger could store an opaque request ID, a reference to the account while processing is underway, the request type, received and completed timestamps, per-store outcomes, and a short exception code. Do not store an export archive or a duplicate of the user's profile in that ledger.

A release checklist for a small team

Before you ship an export or deletion feature, check that you can answer these questions:

  1. Can you find the user's data by account ID and by identifiers used by your vendors?
  2. Is the requester verified at a level appropriate to the information being disclosed?
  3. Does the export distinguish data the user may receive from credentials, other people's data, and internal material that should not be exposed?
  4. Can deletion run again after a timeout without causing inconsistent results?
  5. Are processors, logs, caches, indexes, and backups included in the documented workflow?
  6. Are any retained records tied to a specific reason, access restriction, and deletion or review date?
  7. Can you tell whether every step finished, and respond within the deadline that applies to that request?

Test a normal request, a request for an account with shared data, an export delivery failure, a vendor timeout, and a restore from backup. These tests are about whether your own workflow completes; they do not prove legal compliance. Recheck the relevant rules and vendor processes when your product, user base, or data flows change.

Sources

Leave a Reply