That Database From 2014 Is a GDPR Incident Waiting to Happen
Photo: Columbus Metropolitan Library, No restrictions, via Wikimedia Commons
Every legacy codebase we've audited has the same three things: a folder called misc, a stored procedure nobody dares delete, and personal data in places the developer who wrote it has long since forgotten about.
The ICO doesn't care that your monolith predates the 2018 Act. If you're processing personal data — and you almost certainly are, in ways nobody has documented — the obligations apply. The good news: you can make a serious dent in the risk without freezing feature work for a quarter.
Start With the Logs, Because Everyone Forgets the Logs
The single most common violation in British SME codebases is personal data leaking into application logs. Someone debugging a payment flow in 2016 added a line like logger.info("Processing card for " + customer.email) and it's been quietly hoovering up personal data ever since.
Worse, those logs get shipped to CloudWatch or a Grafana Loki instance, retained for two years "just in case", and never appear on anyone's data map. That's a retention breach and a purpose limitation breach in one line of code.
A quick win: grep your logging calls for field names like email, postcode, dob, phone, or NI number. You'll be surprised what turns up. Then set log retention to something defensible — 30 days is plenty for most operational debugging.
Staging Is Not a Compliance-Free Zone
There's a persistent belief that because staging isn't production, the rules don't apply. They do. A staging database restored from a production snapshot in 2021 is still holding live customer records, often on a box with weaker access controls and a password shared in a Slack channel.
The fix is boring but effective: anonymise your staging data properly. Not "replace surnames with Test1, Test2" — that's trivially reversible and the ICO has been clear that poorly pseudonymised data is still personal data. Use a proper anonymisation tool, or at minimum drop and mask the sensitive columns.
Forgotten Tables and Zombie Backups
Legacy systems accumulate data the way a student house accumulates furniture. Customer tables from a product line you killed in 2019. CSV exports sitting in an S3 bucket nobody owns. Backups on a NAS under someone's desk — yes, that still happens.
Run a data discovery pass:
- List every database, bucket, and backup target you pay for
- For each, ask: what personal data is here, why, and how long has it been here?
- Anything you can't justify, delete or archive offline with a hard expiry date
Data minimisation isn't just a legal principle — it's an incident response strategy. The cheapest breach to report is the one where the data no longer exists.
The Audit That Doesn't Eat a Sprint
You don't need a six-week discovery project. Split the work:
Week one: inventory. One developer, one spreadsheet, every data store. Half a day if you're organised.
Week two: log scrubbing. Grep, triage, fix the worst offenders, adjust retention. A day.
Week three onwards: schedule the staging anonymisation and the backup cull as normal tickets, slotted between feature work. Two hours here, three hours there.
By the end of a month you've addressed the majority of violations we typically find, and — crucially — you can show your working. If the ICO ever comes knocking, a documented, ongoing effort counts for far more than a panicked retrofit after a breach.
Bake It In So You Never Do This Again
The real fix is cultural. Add a data handling checklist to your PR template. Treat a new logging statement that captures user input as a review red flag. Put data retention dates on every backup job you create, so the default is deletion rather than indefinite hoarding.
Legacy code doesn't get cleaner by being ignored, and neither does legacy data. Thirty minutes a week, sustained, will do more for your compliance posture than any policy document pinned to the wall.