A small SaaS data retention policy should answer six questions for each category of personal data: why you keep it, which rule or business need supports that purpose, when the retention clock starts, how long it lasts, what happens at the end, and which systems hold a copy.
There is no universal 30-day, 90-day, or seven-year schedule. The defensible period depends on the data, purpose, jurisdiction, contracts, limitation periods, and any duty to preserve records. This guide gives you a working template and implementation method. It is not legal advice; have counsel validate the periods and exceptions that apply to your company and users.
Most small apps have nothing like this in place. At least 5 of the 21 third-party apps I reviewed in June and July 2026 had personal data (names, health details, tokens, full email lists) exposed somewhere in the schema. Retention was never the thing those reviews went looking for, so it shows up in the notes only where it caused something else: one app kept health details in its logs with no deletion path anywhere in the code. The shape is familiar. A created_at column appears in every scaffolded table; nothing generates the column that says when a row should leave. Data went in, and nothing ever took it back out.
How long should a small SaaS keep user data?
Keep personal data only while the documented purpose still requires identifiable data, unless an applicable legal obligation or legal hold requires longer retention. Then erase it or anonymize it so it can no longer be linked back to a person.
For example, the EU GDPR storage-limitation principle says identifiable personal data should be kept no longer than necessary for its processing purpose, subject to specific safeguards and exceptions. The UK Information Commissioner’s Office similarly says the UK GDPR does not set fixed retention periods. Its storage-limitation guidance calls for justified periods, regular review, and erasure or anonymization when data is no longer needed.
Those are jurisdiction-specific legal examples, not a global retention schedule. Tax, employment, health, financial, consumer, litigation, and sector rules can lead to different answers. The ICO also currently marks parts of its guidance for review following UK legislative changes, which is another reason to record the jurisdiction and verification date beside each legal conclusion.
A retention period is a decision with an owner, trigger, and end action. “Keep forever” is the absence of that decision.
Start with a data inventory, not a number
How to write a data retention policy, in order: inventory first, periods second. A period cannot be enforced until you know where the category travels. Search production systems, operational tools, and processor contracts rather than stopping at the main database.
- 01 Primary database records, including profile, billing, content, and relationship tables.
- 02 Soft-deleted records that the interface hides while the underlying row remains identifiable.
- 03 Application, security, webhook, and model request logs that may contain an account ID, IP address, prompt, or payload.
- 04 Analytics, support, email, and customer-success systems that receive user attributes or event data.
- 05 Uploaded files, generated reports, temporary archives, and manual CSV exports stored outside the app.
- 06 Backups, replicas, data warehouses, and subprocessors with their own deletion or expiry behavior.
For each flow, identify whether your SaaS acts as controller, processor, or both for different data. Under EU and UK GDPR models, a controller decides why and how personal data is processed, while a processor handles it on the controller’s documented instructions. A SaaS acting as a processor should align retention and deletion behavior with the customer contract and documented instructions rather than silently applying its own policy to customer-controlled data. The European Commission’s controller and processor overview explains that division.
One audited app showed how a category grows without anyone deciding it should. A food-delivery marketplace had a notifications table bolted onto the schema late, filled by a database trigger that copied personal details off every order. Its missing row-level security is what got the finding flagged critical, but the duller half of the story belongs here: nothing in that schema gave the table a way to stop growing. The trigger appended a row every time anyone ordered, no purge job or expiry existed anywhere, and the pile of order histories the exposure put at risk got deeper with every week the app ran. A 90-day window would have shrunk that blast radius for free, and nobody had to decide against one; it just never came up.
A small SaaS data retention policy template and example
The table below is a data retention policy example in the sense that matters: a filled-in structure rather than a finished schedule. Other published examples are worth reading for the categories they name. Do not copy someone else’s periods into the blank cells unexamined. The suggested-starting-point column gives an operational default where one is reasonable; it is a place to start, not legal advice, and the basis behind your chosen period still needs an owner to confirm it. Complete one row per category with the person responsible for confirming the legal and operational basis.
| Data category | Purpose and lawful basis | Retention trigger | Suggested starting point | Chosen period or review rule | End action | Exception or legal hold | Systems, processors, owner, evidence |
|---|---|---|---|---|---|---|---|
| Account profile | Define the account purpose and applicable basis | Account closure, contract end, or last activity | While the account remains active | ___ | Erase or anonymize specified fields | ___ | App DB, auth provider; owner: ___; deletion log: ___ |
| Customer content and files | Define why the content is stored | User deletion, workspace closure, or contract end | While the account or workspace remains active | ___ | Delete objects and related metadata | ___ | Object storage, CDN, backups; owner: ___ |
| Billing and transaction records | Service, accounting, and applicable recordkeeping duties | Transaction or financial-period close | Per your tax jurisdiction, often 6-7 years | Confirm per jurisdiction | Minimize or retain required fields only | Tax, audit, claim, or other applicable duty | Billing system, processor, ledger; owner: ___ |
| Support records | Resolve requests and maintain necessary service history | Ticket closure | ___ | ___ | Delete, redact, or anonymize | Active dispute or claim | Help desk, email; owner: ___ |
| Product analytics | Defined measurement purpose | Event date or account closure | 90 days | ___ | Delete or irreversibly aggregate | ___ | Event store, warehouse, analytics processor; owner: ___ |
| Security and application logs | Security, abuse prevention, and diagnosis | Event date | ___ | ___ | Delete or strip identifiers | Incident investigation or legal hold | Log platform, archive; owner: ___ |
Soft-deleted rows (deleted_at) | Honor an undo or recovery window | Soft-delete timestamp | 30 days, then hard-delete or archive | ___ | Hard-delete or archive the row | Active dispute or legal hold | App DB; owner: ___ |
| Webhook and LLM request/response logs | Debugging and incident diagnosis | Event date | 30 days | ___ | Delete or strip payloads | Incident investigation | Logs table, log platform; owner: ___ |
| Abandoned signups, never activated | Complete an unfinished registration | Signup date with no activation | 90 days | ___ | Erase the record | ___ | App DB, auth provider; owner: ___ |
| Generated exports | Fulfil an authorized request | Export creation or download | ___ | ___ | Delete archive and revoke access | ___ | Object storage, delivery service; owner: ___ |
| Backups | Disaster recovery | Snapshot creation | Tied to your rotation schedule, not indefinite | Rotation schedule: ___ | Expire through controlled rotation | Document restoration controls | Backup provider and regions; owner: ___ |
The schedule becomes a useful policy when each row can answer a real question: “Which copy should disappear today, who approved the period, and what evidence proves the action ran?” A privacy notice can summarize relevant periods or criteria for users, while the internal schedule carries the system-level detail.
Choose the retention trigger carefully
“Created at” is not always the right clock. Different categories may begin their period when:
- an account closes;
- a contract or subscription ends;
- a support ticket is resolved;
- a transaction or tax period closes;
- a security event is recorded;
- a user revokes consent, when consent is the applicable basis;
- a legal hold is released.
Write the trigger in terms the database can evaluate. If a policy says “after the customer relationship ends” but no system records that date, the period cannot run reliably.
Turn the schedule into a safe deletion workflow
A scheduled job is one possible enforcement mechanism. It does not make the period lawful and should not run as an unreviewed destructive query. Use a preview, approval, bounded batch, and verification record.
-- Preview candidates for one approved category and cutoff.
select id, occurred_at
from product_events
where occurred_at < :approved_cutoff
and legal_hold_at is null
order by occurred_at
limit :batch_size;
The deletion worker should use the same reviewed predicate, process a limited batch, record counts and failures without copying personal payloads into the job log, and stop when an anomaly threshold is crossed. Run the candidate query in a non-production fixture first. In production, compare the candidate count with the expected range before approving the first destructive batch.
An implementation record should include:
| Control | Evidence to keep |
|---|---|
| Coverage | Category, systems, processor, and approved policy version |
| Candidate preview | Cutoff, row count, sample IDs where appropriate, and approver |
| Hold check | Legal-hold or exception query and result |
| Execution | Job version, start and finish time, deleted/anonymized count, failure count |
| Processor follow-through | API receipt, ticket, or contract-defined confirmation |
| Verification | Repeat query showing no eligible live records remain |
| Recovery | Tested response for an unintended deletion, consistent with backup and privacy obligations |
Rollback needs careful wording. A recovery plan can protect against an erroneous purge, but it should not restore records that were correctly deleted under the policy. Test the job on synthetic fixtures and use staged batches so rollback is an exceptional safety measure rather than part of normal retention.
How should backups fit the retention policy?
Document the backup rotation, restore access, and what happens when an expired record appears in a restored snapshot. Live deletion and backup expiry are separate controls. A backup may retain a historical copy until its established cycle overwrites it, depending on the applicable law and your circumstances. Keep that copy beyond normal operational use, prevent it from re-entering production silently, and ensure the deletion is reapplied after an authorized restore.
A backup data retention policy is a separate row on the schedule for exactly that reason: the live period and the snapshot rotation run on different clocks, and only one of them is under your direct control.
The UK ICO’s erasure guidance discusses putting backup data beyond use until it is overwritten under an established schedule. That guidance is UK-specific and does not eliminate the need to check other jurisdictions, contracts, or sector rules. Testing the Supabase backup and restore path is one example of verifying the technical half of the policy.
A GDPR delete request raises the same backup question in a sharper form, and the answer there belongs to a runbook rather than a schedule: erase from live use, let the established rotation expire the snapshot, and make sure an authorized restore cannot quietly put the record back.
Retention policy review checklist
Review the schedule when the product adds a new data source, processor, purpose, jurisdiction, or contract type. Also review it on a fixed cadence even when the product appears unchanged.
- Confirm that every category still has a current purpose and owner.
- Recheck legal periods and source links with counsel.
- Compare the schedule with the current schema, storage buckets, logs, processors, and manual exports.
- Test preview and deletion jobs against synthetic records.
- Verify that holds block deletion and that expired holds are released.
- Confirm processors and subprocessors follow the agreed deletion behavior.
- Record the date, reviewer, policy version, and resulting changes.
Retention lowers the volume of stale data available to a bug, breach, or later rights request, but it does not replace access control. Data-loss controls cover the separate risk of deleting too much or restoring too little. The written schedule should map to the code and storage paths it governs.
Retention handles routine lifecycle decisions; that second problem, what to do when a deletion request actually lands, is its own runbook.
Exports pull in the other direction. A user-data export creates a fresh copy of personal data on purpose, so the archive it produces needs a retention row of its own rather than an indefinite home in object storage.
Common questions about SaaS data retention
What is a data retention policy?
A data retention policy is the written record of how long each category of personal data is kept, why, when the clock starts, what happens at the end, and who owns that decision. It is a set of decisions with an owner, not a script. A scheduled job can enforce part of it once the decisions exist.
What is a good data retention policy?
A good one is enforceable. Every category names a purpose, a lawful basis or business need, a trigger the database can evaluate, a period, an end action, an exception rule, the systems holding a copy, and an owner. If a row cannot answer “which copy disappears today, and who approved that period?”, what you have is a statement of intent rather than a policy.
Can you provide an example of a data retention policy?
Yes: the schedule table above is one, laid out row by row with the columns a small SaaS actually needs. Create your version by completing one row per category rather than adopting the periods shown. The suggested starting points are operational defaults, and the basis behind each chosen period still needs an owner to confirm it.
Does GDPR set a fixed data retention period?
No general fixed period applies to every category. Under EU and UK GDPR storage-limitation principles, the period must be necessary for the documented purpose, subject to applicable obligations and exceptions. Other laws can impose specific periods. Record the jurisdiction and obtain legal advice for your schedule.
Is anonymized data still personal data?
That depends on whether a person can reasonably be reidentified using the remaining data and other means likely to be used. Replacing an email with a stable user ID or hashing it may leave the person linkable. Treat pseudonymization as a security measure, not automatic proof that the data is outside privacy law.
Can I use one retention period for the whole database?
That is rarely a good model. Account data, transactions, security logs, support records, and generated exports have different purposes and triggers. Category-level periods make the policy explainable and enforceable.
Is a cron job a data retention policy?
No. The policy records the purpose, basis, trigger, period, end action, exceptions, systems, and owner. A cron job can enforce part of that decision after preview, approval, and testing.
How often should a small SaaS review its retention schedule?
Choose and document a cadence based on risk and rate of change, then add event-driven reviews for new data sources, purposes, processors, jurisdictions, and legal requirements. The important evidence is that the review happens and reaches the systems that actually store the data.
When the app carries customer access or revenue
AxonBuild fixes the payment, billing, access, or data-handling failure, verifies the result, and adds a check that catches it before it interrupts the business again.