Back to BlogArchitecture & Engineering

Data Retention and Deletion in a SaaS: Export, Purge and Legal Hold

Rupak Amin

Founder & Lead Engineer, RAITHub

9 min read

RAITHub ships and tests production software. See QA as a Service or talk to us.

Build retention and deletion as a system, not a delete button: set a retention period per data type, soft-delete first so an accident is recoverable, then hard-delete on a schedule when the period passes; give each user a machine-readable export of their data; honour a legal hold that freezes deletion; and plan how deleted data ages out of backups and logs, which is where "deleted" usually isn't.

This is engineering guidance for SaaS on PostgreSQL. Retention periods and deletion rights are legal questions that vary by data type, industry and country; this is general information, so confirm the specifics with your adviser. If you would rather have it built and tested for you, see how RAITHub would build this below.

Why isn't deleting a row enough?

Because a real user is spread across many tables, referenced by orders and audit logs, copied into caches and search indexes, and present in every backup taken while they were active. A single DELETE leaves most of that behind, and a hard delete done too eagerly can break records you are required to keep, such as invoices. Deletion needs a plan per data type: what can go, what must stay, when, and how it leaves the places you forget.

Data typeTypical handling on account closureWhy
Profile and contentDelete after a grace periodNo reason to keep; the user asked
Invoices and tax recordsRetain for a legally required periodAccounting and tax law often require it
Audit logRetain per policy, then drop by partitionSecurity and dispute evidence
References (orders, messages)Anonymise rather than deleteDeleting would break others' records
BackupsAge out with the backup rotationRewriting backups is impractical

Soft delete or hard delete, and when?

Use both, in sequence. Soft delete marks a row deleted and hides it, so a mistaken deletion or a changed mind is recoverable during a grace period. Hard delete removes the bytes once the retention period passes. Soft delete alone is not real deletion, the data is still there, so a soft delete with no scheduled purge does not satisfy a deletion request.

-- Soft delete: mark, hide, keep recoverable during the grace period.
ALTER TABLE users ADD COLUMN deleted_at timestamptz;

-- Every normal query excludes soft-deleted rows (enforce with a view or RLS).
-- SELECT * FROM users WHERE deleted_at IS NULL;

-- A retention policy row per data type drives the purge.
CREATE TABLE retention_policies (
  data_type     text PRIMARY KEY,   -- 'user_content' | 'invoice' | 'audit_log'
  grace_days    int  NOT NULL,      -- soft-deleted this long, then purged
  legal_min_days int                 -- a floor the purge must not cross (NULL = none)
);

Record why something is retained past a deletion request, usually a legal minimum such as tax records, so the exception is deliberate and documented, not an oversight.

How does the purge job actually run?

A scheduled job finds rows whose grace period has passed, checks no legal hold applies, and hard-deletes them in batches. Run it regularly, log what it removed (counts, not contents), and make it idempotent so a retry does no harm. The scheduler and job patterns are in the scheduler and recurring jobs guide.

-- Daily purge: hard-delete soft-deleted users past their grace period and not on hold.
WITH due AS (
  SELECT u.id
  FROM users u
  JOIN retention_policies p ON p.data_type = 'user_content'
  WHERE u.deleted_at IS NOT NULL
    AND u.deleted_at < now() - make_interval(days => p.grace_days)
    AND NOT EXISTS (SELECT 1 FROM legal_holds h WHERE h.user_id = u.id AND h.released_at IS NULL)
  LIMIT 500            -- batch, so one run never locks the table for long
)
DELETE FROM users WHERE id IN (SELECT id FROM due);

Deletion must reach beyond the primary table: drop the user from caches and search indexes, remove their uploaded files from object storage, and anonymise references you cannot delete. An order a deleted user placed stays for the seller's records, but the personal fields on it are replaced with a tombstone ("deleted user"), so the order survives and the person does not.

What about data in backups and logs?

This is where "we deleted it" quietly becomes untrue. A backup taken last week still holds the user you purged today, and application logs may contain their data for the log retention period. You usually cannot rewrite backups, so the honest, workable approach is: keep backups on a defined rotation so the data ages out within a bounded time, do not restore-and-republish deleted records, and keep personal data out of logs in the first place. State your backup retention window, because it is the real maximum lifetime of "deleted" data. Guidance from data-protection regulators, such as the UK ICO on the right to erasure, accepts that data beyond live systems can be put "beyond use" and deleted in the normal course of backup rotation rather than instantly. Confirm your own obligations with your adviser.

How do you give a user their data export?

Alongside deletion, offer export: a machine-readable file (JSON or CSV) of the personal data you hold about a user, produced on request. Build it as a background job that gathers the user's rows across tables, writes a file to object storage, and hands back a short-lived signed link, using the storage and signed-URL pattern in the file storage and sharing guide. Export and deletion are two sides of the same data-subject request, so build the query that finds "everything about this user" once and use it for both.

Do-it-yourself estimate: 1–2 weeks for soft delete, a retention-policy table, a purge job, export and legal hold, if the data model is clean; longer where personal data is scattered or stored in logs. The main risks are soft delete with no purge (data that was never really deleted) and personal data hiding in logs, caches and backups.

Buy, build or hire?

OptionExamplesChoose this whenWatch out for
A privacy/consent platformA hosted data-subject-request toolYou want a request intake and workflow quicklyIt orchestrates requests; the actual deletion across your data is still your code
Framework soft-delete pluginAn ORM soft-delete extensionYou need the soft-delete flag and query filteringPurge, legal hold, backups and cross-system deletion are not covered
Custom retention buildThe design in this guideDeletion must span your tables, files, caches and references correctlyYou own the purge, holds, anonymisation and backup policy
Hire a team to build itRAITHub or another studioYou need export and erasure to be complete and testableGet the purge and legal-hold tests in the handover

How do you test retention and deletion?

  • Soft then hard: soft-delete a user, assert they are hidden and recoverable, advance time past the grace period, run the purge, and assert the data is gone.
  • Legal hold: place a hold, run the purge, and assert the held data survives; release the hold and assert it then purges.
  • Cross-system: after purge, assert the user is absent from search, caches and object storage, and that references are anonymised, not broken.
  • Export completeness: assert the export contains the user's rows from every table that holds their data.
  • Retained records: assert invoices and audit entries survive deletion as the policy requires.

How RAITHub would build this

  • Policy model: a retention period per data type, with legal minimums recorded, driving a soft-delete-then-purge flow.
  • Purge and reach: a batched, idempotent purge job that also clears caches, search and object storage and anonymises references.
  • Rights: user data export and erasure built from one "everything about this user" query, with legal hold overriding deletion and a stated backup window.
  • Tests: soft-then-hard, legal-hold, cross-system and export-completeness tests in CI.

Timeline: retention and deletion inside a new SaaS build fits the 4–6 week fixed scope; retrofitting an existing product is a bounded piece in the 6–12 week backend range. You receive: deletion and export tests in CI, handover docs and runbooks, and full IP under NDA. RAITHub is not certified to any compliance standard and signs DPAs and SCCs; legal retention requirements are yours to confirm with your adviser.

Next step: a free 15-minute technical audit, then a written fixed quote. See the SaaS development service, read the audit log design guide for the records that survive deletion, and the data-handling approach in outsourcing from Germany: GDPR and the DPA. Book the audit.

Frequently asked questions

Should I use soft delete or hard delete in a SaaS?

Both, in sequence. Soft delete hides a row and keeps it recoverable during a grace period; hard delete removes the bytes once the retention period passes. Soft delete alone is not real deletion, so it must be followed by a scheduled purge.

How do I delete a user whose data is referenced everywhere?

Delete what you can, anonymise what you cannot. An order a deleted user placed stays for the seller's records, but its personal fields are replaced with a tombstone. This keeps other records intact while removing the person's data.

What happens to deleted data in backups?

You usually cannot rewrite backups, so deleted data ages out with the backup rotation. Keep backups on a defined window, do not restore-and-republish deleted records, and state the window, since it is the real maximum lifetime of "deleted" data. Confirm your obligations with your adviser.

How long should a SaaS keep user data?

It depends on the data type, your industry and your country: some records, like invoices and tax data, have legal minimums, while profile data can go soon after an account closes. Set a retention period per data type and document any exception. This is general information; confirm with your adviser.

What is a legal hold, and why does it override deletion?

A legal hold freezes deletion of specific data because it may be needed for litigation, an investigation or a regulator. The purge job must skip held data and only remove it after the hold is released, so a hold always takes precedence over a retention schedule.

data retentiondata deletionGDPRsoft deleteSaaSprivacyPostgreSQL

Ready to discuss your project?

Book a free 15-minute technical audit with our engineering team.