You Can Export Your Data. You Can't Export Your Business.
Since 12 September 2025 an EU cloud provider has had to let you leave inside 30 days, and from 12 January 2027 it cannot charge you for the exit. GDPR has given you a right to your own data since 2018.
All of it is satisfied by a folder of CSVs.
Nobody is exploiting a loophole here. A file per object is a structured, commonly used, machine-readable format, which is the standard the law sets, and it is literally what you asked for. It is also close to useless. A file per object carries every row you have and none of the relations between them.
Rows move fine. What you run the company on is which row points at which.
Every export gives you rows. The value was in the joins.
Run the export on your CRM and you get accounts.csv, contacts.csv, opportunities.csv, tasks.csv, emails.csv. Every file is correct. Every field is there.
Now ask a question you run the company on. Which renewal is at risk, and why? Answering it means walking four of those files in order: this renewal belongs to that account, which arrived through that campaign, and the reason it nearly went in March is a comment on a task owned by someone who has since left. One fact, and it exists only in the pointers between the files.
The export carries those pointers as foreign keys. A Salesforce foreign key looks like 0035f00000AbCdEfGHI, and it resolves in exactly one org: the one you are leaving. On the far side it is eighteen characters of nothing. You have every record you ever created and no way to say which belongs to which.
You do not need Salesforce for this. Export the invoicing tool a one-person consultancy runs on and you get clients.csv, projects.csv, time_entries.csv, invoices.csv, expenses.csv. Same five files, same problem: which hours belong to which project, which project billed on which invoice, and which of the two clients called Bright the retainer belongs to. The scale changes. The failure does not.
Formula fields never reach the file
Some of it is not in the folder at all.
One walkthrough of the export limits, updated for Winter ‘26, notes that formula and roll-up summary fields do not export, because Salesforce computes them at read time. Every derived number your team looks at daily, the account totals, the weighted pipeline, the days-since-last-touch, exists only while you are logged in.
Attachments come out as rows describing attachments, with the bytes retrieved separately. Automation rules, permission structure, field definitions as opposed to field values, approval chains, and the audit trail are not objects the export has a file for. You get the current state of every record and no account of how it got there.
That last one is worth sitting with. Six years of decisions produced the row. You are handed the row.
Your lead scores are legally theirs
The law is narrower than the marketing around it.
Article 20 covers data the subject provided, and the Article 29 Working Party guidance reads “provided” to include observed data, what the service watched you do, while excluding inferred and derived data: the outputs the controller generated by analysing the rest.
Which is to say the lead score is not portable. Nor is the churn probability, the health score, the behavioural segment, or the customer lifetime value. The vendor built those, so the vendor keeps them, and the reasoning is defensible: they did build them.
The effect is still that the portable half of your CRM is the half you typed in, and the half you make decisions with stays behind. You can take the raw material of the judgement and not the judgement.
Rebuilding the graph means matching on email addresses
So you rebuild. With the vendor ids meaningless, the only way to reconnect a contact to an account is to match on the columns that survive: names, email addresses, domains, dates.
That is entity resolution, and entity resolution is wrong a small percentage of the time by construction. Two people share a Gmail account. A company appears as “Acme”, “Acme Ltd” and “ACME LIMITED”. Someone changed employer and kept replying from the old address for a month.
The starting material is worse than the plan assumes. A benchmark from 87 HubSpot implementation partners, cited by Syncmatters across roughly 2,800 migrations, puts duplicate contact records in 85% of systems and inconsistent company names in 72%. The underlying report is not published, so treat the exact figures as an order of magnitude. Anyone who has run a migration will recognise the direction.
A few percent wrong, across five objects, is a system you stop trusting in the second week. And a business that does not trust its own records is running on a spreadsheet somebody keeps privately, which is where you were before you bought the tool.
This is why an 11.4% rise sticks
SaaS prices rose 11.4% against 2.7% general inflation, and almost nobody moved. The usual explanation is inertia, or switching costs, said vaguely enough that it sounds like a preference.
Price it out. A quarter of an engineering team for a quarter, rebuilding every reference from email addresses, followed by a year of people finding records attached to the wrong account. Against that, an annual increase of a few hundred pounds a seat is cheap, and every vendor’s finance team has run the arithmetic you just did.
Alone, it is the same sum with your name in every row. You are the engineering team. Moving three tools is a fortnight of evenings pointing records back at each other, then six months of finding a March invoice filed against last year’s client, and the evenings are hours you would otherwise have billed. Nobody signs that off, because there is nobody to sign it off. The uplift goes through on the card that is already on file.
The export button is what makes the lock look optional. Compliance is satisfied, the folder downloads, and you stay.
Where a plain export is enough
The argument has limits, and they are worth naming.
Email solved this. IMAP means your mail is a protocol rather than a product, and moving providers is an afternoon. Calendars mostly solved it. Password managers, bookmark tools and note apps export cleanly for the same reason: there is barely a graph to lose, so a flat file is a fair representation of the thing.
The EU Data Act is also a genuine improvement, and the switching-charge deadline in January 2027 will make some of this cheaper. It sets a floor under exit terms that did not previously exist.
And the objection that points at us: holding the file is not the same as being able to read it in ten years. A local proprietary schema is still a proprietary schema. If our answer to lock-in were “the database is on your disk”, we would be selling a nicer lock, and you would be right to say so.
What portability would have to mean
Four properties, and the export button gives you none of them.
You hold the store the application reads from. A copy is a snapshot, and it starts drifting the moment it is written.
The references are modelled. If a task can reference the customer it belongs to as a first-class relationship, that relationship is in the backup because it is in the database. Nobody rebuilds it from email addresses.
The ids are yours. A foreign key is only useful while you can dereference it, which means the rows it points at have to be somewhere you still have access to.
The schema is documented and readable without the vendor. This is the one that answers the objection above. A schema you can open, read, and query with standard tools is a schema you can leave, at a cost you can estimate in advance.
Ion Alpha keeps the database on your machine
Ion Alpha is one PostgreSQL schema, on your hardware, holding research, planning, code, content, communication, operations and distribution together. 74 modules write into it. 448 SQL migrations are the schema’s history, in the repository, in order, as plain SQL.
The relationships are modelled. Ownership runs as a tree, instance to project to workspace, and everything else connects through src/base/relationships and src/base/links, which impose no hierarchy at all. A task can point at the customer, the deployment, the research session and the invoice, and each of those pointers is a row you can query.
So the export story is pg_dump. You get the tables, the foreign keys, the constraints and the derived columns, and the keys still resolve, because the database they point into is the one sitting on your disk. There is no portability feature, and no roadmap item for one. The condition that makes exports lossy, your system of record living somewhere you can only reach through an API, is the condition we removed.
It is still our schema. Moving to a different product means mapping 448 migrations’ worth of tables onto someone else’s model, and that will take an engineer weeks. You are the operator: your backups, your Postgres, your afternoon when something breaks, and no support desk holding a copy. If you run a studio and someone is going to ask who they call at 2am, the honest answer is nobody. What bounds it is that the store is standard Postgres on hardware you control, so any contractor who can read SQL can get at your data without our help or our permission. For some businesses that is enough and for some it is not, and you should decide which you are before you buy, rather than after.
What you get for it is the ability to price the exit before you commit to the entrance. Open the schema, read the tables, decide. That is more than the export button has ever offered, and considerably more than the renewal quote in your inbox.
Sources
- EU Data Act Begins September 12, Morgan Lewis
- Data Act Article 29: Gradual Withdrawal of Switching Charges, Data Act Kit
- Guidelines on the Right to Data Portability (WP242), Article 29 Working Party
- Salesforce Data Export Limits, Winter ‘26 Update, Xappex
- Why CRM Data Migration Is Still the Biggest Bottleneck, Syncmatters
- Cloud Switching Under the EU Data Act, Greenberg Traurig