Data Minimisation and Retention: Engineering It
Turn GDPR data minimisation and storage limitation into engineering: retention schedules, TTLs, partition drops, crypto-shredding, backups and test data.
Every byte of personal data you store is a byte you must secure, back up, disclose in a breach notification and eventually delete. Data minimisation and storage limitation are often presented as legal principles for the privacy team, but in practice they are engineering problems: which fields a form collects, which columns a table keeps, how long logs sit in a bucket, what happens to a customer record three years after the contract ends, and whether a backup restored in 2028 quietly brings back data you deleted in 2026. This guide translates the principles into schedules, patterns and code that security and IT teams can implement and evidence.
The legal anchors
Two principles in Article 5(1) set the requirement:
- Article 5(1)(c), data minimisation. Personal data must be adequate, relevant and limited to what is necessary in relation to the purposes for which it is processed.
- Article 5(1)(e), storage limitation. Personal data must be kept in a form that permits identification of data subjects for no longer than is necessary for those purposes.
Article 25 turns these principles into a design obligation. Article 25(1), data protection by design, requires appropriate technical and organisational measures designed to implement principles such as minimisation effectively. Article 25(2), data protection by default, requires that by default only personal data necessary for each specific purpose is processed, and it names four dimensions: the amount of data collected, the extent of processing, the period of storage and accessibility. Recital 39 adds that retention should be limited to a strict minimum and that the controller should establish time limits for erasure or for a periodic review.
Two further points matter for security teams. First, these principles sit in Article 5, and infringements of the basic principles fall under the higher fine tier in Article 83(5). Second, over-retention amplifies every other risk: a breach of a database holding ten years of former customers is a larger breach than one holding only active customers.
Minimisation starts at collection
Minimisation is cheapest at the point of design. Before a new system or feature ships, ask for each field:
- What purpose does this field serve, and is that purpose recorded in the record of processing?
- Would a less precise value work? A year of birth instead of a full date, a region instead of a full address, an age band instead of an age.
- Does the field need to be identifiable at all, or would a pseudonymous identifier do? See our guide on pseudonymisation versus encryption.
- Who needs access? Accessibility is one of the four default dimensions in Article 25(2), so role-based access and field-level masking are minimisation measures too.
Free-text fields deserve special attention. Support tickets, comments and notes attract data nobody planned to collect, including health information or identity document numbers. Consider input guidance, pattern detection for obvious identifiers and shorter retention for free text than for structured data.
Building a retention schedule
A retention schedule links each data category to a retention period, a trigger event and a disposal action. The period is a business and legal decision (driven by purpose, contractual needs, statutory obligations and limitation periods under national law), which is why the DPO and legal counsel must validate it. The IT team's job is to make each row technically enforceable and verifiable.
| Data category | Trigger | Retention period (example) | Disposal action | Enforced by |
|---|---|---|---|---|
| Customer account data | Account closure | Set by legal/DPO | Delete or anonymise | Nightly purge job |
| Support tickets | Ticket closure | 24 months | Delete ticket and attachments | SaaS automation rule |
| Web server access logs | Log creation | 6 to 12 months | Drop daily partitions | Partition drop job |
| Security audit logs | Log creation | Per logging policy | Expire from SIEM index | Index lifecycle policy |
| Job applicant files | End of recruitment | Set by legal/DPO | Delete | ATS retention setting |
| Backups | Backup creation | 35 days | Expire snapshot | Backup policy |
The periods above are placeholders to show structure, not recommendations. For logs, the French supervisory authority (CNIL) recommended in its 2021 logging recommendation a retention of six months to one year as a general rule, unless a legal obligation or specific risk justifies otherwise; it is a useful benchmark, but check your own supervisory authority's guidance. Our guide on security logging and monitoring covers log retention in more depth.
Technical deletion patterns
Time-to-live (TTL)
Many data stores support expiry natively: TTL indexes in document databases, key expiry in caches, object lifecycle rules in cloud storage. TTLs are ideal for data with a fixed lifetime from creation, such as sessions, one-time tokens, raw telemetry and temporary exports. They are less suitable when the trigger is a business event (contract end), because the expiry time is not known at write time.
Partition drop
For large append-only tables such as logs and events, row-by-row DELETE is slow, generates heavy write-ahead log traffic and leaves bloat behind. Time-based partitioning lets you drop an entire day or month in one metadata operation. A PostgreSQL example:
-- Access log table partitioned by day
CREATE TABLE access_log (
logged_at timestamptz NOT NULL,
client_ip inet,
user_id bigint,
path text,
status smallint
) PARTITION BY RANGE (logged_at);
CREATE TABLE access_log_2026_09_28 PARTITION OF access_log
FOR VALUES FROM ('2026-09-28') TO ('2026-09-29');
-- Retention job: drop partitions older than the retention period
-- (run daily from a scheduler; log each dropped partition as evidence)
DO $$
DECLARE
part record;
cutoff date := current_date - INTERVAL '180 days';
BEGIN
FOR part IN
SELECT c.relname
FROM pg_inherits i
JOIN pg_class c ON c.oid = i.inhrelid
JOIN pg_class p ON p.oid = i.inhparent
WHERE p.relname = 'access_log'
AND to_date(right(c.relname, 10), 'YYYY_MM_DD') < cutoff
LOOP
RAISE NOTICE 'Dropping partition %', part.relname;
EXECUTE format('DROP TABLE %I', part.relname);
END LOOP;
END $$;
For event-triggered retention in operational tables, a scheduled job that deletes or anonymises rows based on a status and date column is usually enough:
-- Anonymise closed accounts after the retention period
UPDATE customer
SET email = NULL,
full_name = NULL,
phone = NULL,
anonymised_at = now()
WHERE closed_at < now() - INTERVAL '3 years'
AND anonymised_at IS NULL;
Remember that anonymisation must be genuine: if the remaining columns still allow a person to be singled out or linked to other data, the result is still personal data. See the glossary entry on anonymisation.
Crypto-shredding
Crypto-shredding encrypts data per data subject or per dataset with separate keys. Destroying the key renders all copies of the ciphertext unintelligible, including copies in replicas, caches, exports and immutable backups. It is particularly useful where you cannot rewrite storage, such as write-once archives or event-sourced systems. The design requirements are strict: keys must live in a key management system separate from the data, key destruction must itself be logged, and no plaintext copy may exist outside the encrypted store (search indexes and analytics copies are common leaks).
Backups and logs
Backups are the usual objection to deletion. Common practice, accepted by many supervisory authorities, is that data in backups is treated as erased once the backup expires under its normal rotation, provided the backup is not restored into production in the meantime, and that if a restore occurs, the deletions made since the backup was taken are re-applied. That practice is not a rule written in the GDPR, so document it in your retention policy and confirm it with your DPO. Operationally, this means:
- keep backup retention short and defined, and record it in the schedule;
- keep a deletion journal (identifiers only, minimised) so deletions can be replayed after a restore;
- restrict backup access and encrypt backups, consistent with Article 32(1)(c) on timely restoration.
Logs are personal data whenever they contain IP addresses, user identifiers or email addresses. Apply retention at every hop: the application, the log shipper buffer, the SIEM hot tier, cold storage and any analytics export.
Test data from production
Development, test and staging environments generally have broader access and weaker monitoring than production. Copying a production database into them multiplies the places where personal data lives, often without any retention control. Prefer, in order:
- Synthetic data generated from the schema.
- Masked or pseudonymised extracts, restricted to the tables and columns the test needs.
- Full production copies only with a documented justification, production-grade controls and a fixed expiry.
Evidence and verification
Under Article 5(2), you must be able to demonstrate compliance. For each schedule row, keep: the configuration or code that enforces it, job run logs showing it executed, and a periodic check (for example, a query counting records past their retention date that should return zero). Treat a non-zero result as a finding with an owner.
Scope of this guide
This article is technical guidance for security and IT teams implementing minimisation and retention controls. It is not legal advice. Retention periods, legal obligations to keep data and the treatment of backups should be confirmed with your DPO or legal counsel and checked against your national supervisory authority's guidance.