GDPR Retention for Laravel Form Submissions: Delete, Anonymize, or Archive?
GDPR Retention for Laravel Form Submissions: Delete, Anonymize, or Archive?
There is no GDPR-wide default period for contact-form data. A controller chooses and documents retention based on purpose, legal basis, necessity, statutory or contractual duties, limitation periods, risk, and applicable local law.
This article is engineering information, not legal advice. Special-category, children’s, criminal-offence, health, employment, and sector-regulated data require additional analysis with qualified counsel or a DPO.
Inventory by purpose, not table
A form answer rarely exists only in form_submissions. Map every copy:
- live database and uploaded files;
- email and notification bodies;
- CSV/PDF exports;
- analytics events and logs;
- webhook delivery records;
- CRM, Sheets, Airtable, or other integrations;
- backups and disaster-recovery replicas.
For each purpose, record data categories, legal basis, recipients/processors, locations, retention trigger, period/review, deletion method, and accountable owner. The official GDPR text establishes data minimization and storage limitation; it does not provide one number that fits every form.
Store a trigger and policy version
“Created plus N days” is one trigger. Others include case closure, event end, hiring decision, contract termination, or withdrawal/objection where applicable.
Persist the applied policy/version and preferably expires_at at collection. This makes later policy changes deterministic and auditable. Add a hold state with owner, reason, start, review date, and release path. A hold must not become undeclared permanent storage.
Delete, anonymize, and archive mean different things
Delete data when it is no longer necessary and no valid exception or obligation applies.
Anonymize only when the result cannot reasonably single out, link, or support inference about a person. Removing a name or hashing an identifier is commonly pseudonymization, not proof of anonymization. The EDPB guidance emphasizes singling-out, linkability, and inference.
Moving data to an archive is still processing personal data. The archive needs a justified purpose, access controls, retention, and rights handling.
Prune without losing dependent cleanup
Laravel's Prunable supports a per-record pruning() hook, useful for deleting associated files before the row disappears. MassPrunable uses mass-delete queries and does not call pruning, deleting, or deleted events. Do not use it when every submission requires file or integration cleanup unless that cleanup is handled separately and proven.
Review Laravel model pruning, run model:prune --pretend during rollout, process bounded batches, prevent overlap, and use a one-server lock in multi-node deployments.
Log non-PII counts and outcomes. A failed item should retry without extending every other record's retention.
Propagate deletion
Deleting the source row is not enough when a webhook copied the answer into a CRM or an export remains on object storage. Maintain a recipient registry and deletion workflow. Expire export artifacts and signed links.
Backups may follow an established overwrite schedule when surgical removal is infeasible. Put affected data beyond normal use, document the schedule, and ensure a restore is passed through a deletion ledger before re-entering active processing. Be transparent about the distinction.
Separate expiry from rights requests
A scheduled retention job and an Article 17 request are related but not identical. Erasure has conditions and exceptions; it is not absolute in every case. Route legal-basis, claims, statutory-retention, and public-interest questions to the accountable legal/privacy role.
Self-hosting does not itself produce GDPR compliance. It changes the deployment and processor map while the deploying organization remains responsible for its controller/processor analysis and downstream services.
A useful policy matrix
| Purpose | Trigger | Decision inputs | Action |
|---|---|---|---|
| Sales enquiry | Resolution or last contact | Need, limitation periods, CRM policy | Delete/minimize |
| Support case | Case closure | Warranty/contract/security needs | Delete or retain bounded record |
| Job application | Hiring decision | Employment law and future-role consent | Delete/retain by documented basis |
| Event payment evidence | Event/transaction date | Tax/accounting duties | Separate evidence from optional answers |
| Product analytics | Collection window | Purpose, linkability, ePrivacy rules | Aggregate/delete identifiers |
| Abuse/security log | Security event | Threat investigation need | Restrict and expire |
The period column belongs to the organization and jurisdiction, not a generic blog recommendation.
Tests and operational evidence
- exact cutoff in the application timezone;
- held records survive and released holds become eligible;
- files and dependent delivery records follow policy;
- tenants/forms retain their own policies;
- reruns are idempotent after partial failure;
- dry-run counts match the deletion query;
- restored backups reapply the deletion ledger;
- data claimed as anonymous passes a documented linkability assessment.
The broader GDPR form checklist covers collection and transparency, while the upload guide covers private document handling. Retention becomes credible when every copy has an owner, trigger, action, and test.