The Door Marked Exit: Proving Your Customer Data Can Actually Leave
Photo: DFID - UK Department for International Development, CC BY 2.0, via Wikimedia Commons
Most software teams have an export button somewhere. It sits in settings, usually next to a danger zone, and it looks reassuring. The trouble is that nobody presses it unless something has gone wrong: a customer is leaving, a contract has ended, a regulator has asked a question, or a support case has escalated to the point where calm words are no longer enough.
That is a poor time to discover the export contains half the record. Or that it opens only in a spreadsheet from 2011. Or that it silently drops attachments, notes, consent history and the one table that the finance team cares about most.
Data portability should be treated as a design constraint, not a compliance checkbox. If you build a UK service that holds personal data, the export path deserves the same attention as login, payments or backups. Not because it is glamorous, but because it is one of the few features whose failure is felt by someone outside the team, often at the worst possible moment.
An export is a promise, not a page
The legal language around portability can be fuzzy in everyday engineering conversation, so keep the technical promise simple: if a customer asks for their data, we can give them a complete, understandable, machine-readable copy in reasonable time, and we can explain what is included.
That promise has consequences. It means your schema needs stable identifiers. It means uploaded files need a route out of object storage. It means audit logs, consent records and derived data need a clear policy: included, excluded, or summarised with a reason. It means support staff need a runbook that does not rely on a single engineer who remembers the SQL.
In the UK, the relevant frame is usually UK GDPR, including the right to data portability where it applies. This is not legal advice, and your legal team should have the final word. But engineering teams should not wait for a legal memo to notice that the export is broken. The practical work starts with a question: what would a complete record actually look like to the person receiving it?
What goes in the box
Start with a manifest. A good export is not a zip file with a database dump and a hopeful README. It is a set of files that a human can understand and a script can parse. Think CSV or JSON for structured records, original file formats for uploads, and a plain-text manifest that says what each file contains, how it relates to the others, and what has been left out.
For a typical service, that might include account details, contact history, orders or bookings, messages, consent preferences, uploaded documents, and a log of key account events. Derived data is where teams get caught. A recommendation score, a risk flag or a summary table may not be personal data in isolation, but it can be personal data in context. Decide deliberately rather than letting the export query miss it by accident.
Then think about the shape. A customer should not need your internal ID scheme to make sense of their own data. Use readable column names. Include timestamps in ISO 8601 with an explicit time zone. Avoid nested JSON that requires a bespoke parser unless the receiving system genuinely needs it. If you offer both a human-readable CSV and a machine-readable JSON bundle, say which is which in the manifest.
Run an escape rehearsal
Once a quarter, pick a real but anonymised customer record and export it as if they had asked. Then do the boring, revealing work: open every file, count the rows, match the attachments, check the dates, and try importing the result into a clean spreadsheet or a small script. Give it to someone who did not build it. Watch where they hesitate.
This is not a compliance audit with a clipboard. It is a rehearsal, like testing a fire door. You want the awkward discoveries to happen on a Tuesday afternoon, not during a contract negotiation.
A useful rehearsal has three passes. First, completeness: does the export account for every table and file type that holds customer data? Second, usability: can a non-engineer find the order history without a decoder ring? Third, timing: how long does it take, and does it hold up for your largest customer? That last one matters. An export that works for a test account with twelve rows can fall over for an organisation with years of activity and a shared inbox full of attachments.
Keep a short record of each rehearsal: date, record used, checks performed, problems found, owner, and when fixed. That record is useful to support, engineering and legal alike. It also stops the same gap being rediscovered every eighteen months.
The conversations that stop the scramble
An export path is not owned by engineering alone. Support needs to know how to verify identity before handing over data. Operations needs to know who runs the export and where the file is stored afterwards. Legal and privacy need to agree what is included, what is redacted and what is refused, with reasons. Product needs to understand that changing the schema can break the manifest.
Have those conversations before the quarterly rehearsal, not after it. A simple shared document works: what the export contains, who can request it, how identity is checked, expected turnaround, storage and deletion rules, and the escalation route when something looks wrong. Update it when the schema changes.
There is a cultural point here too. Teams often treat portability as an admission that customers might leave. In reality, a clean exit is part of trust. It says you are not holding data hostage, and that your system is legible enough to explain itself. That is a good signal to send, even to customers who never press the button.
The export button you hope never to press should still be the one you have tested most recently. Build it like a door, not a decoration. Then rehearse opening it while the building is quiet.