Leaving juudd is a call your assistant makes. There is no form to fill in, no email to send, no notice period, and nobody here to ask.
That is the kind of sentence every platform writes, so here is the part of it you can check instead of believing. The exit is a short list of tool names inside the code that decides what an account may do, and that list keeps working in the one situation where a platform has the most to gain from it not working.
Lock-in is usually an accident, not a strategy
For the first eleven tools here, everything that touched a site's code wrote. One put files in. One moved a stored version to the front. One named the versions without opening any of them. Nothing handed anything back.
Meanwhile the database could already leave. A single call handed a customer their entire database and could not get it back. So for a while the data could walk out and the code could not, and nobody had ever argued for that — it was the order the tools happened to get built in.
A platform that lets the database out of the door and keeps the source is holding customers by an oversight.
That line is from the decision that closed it, and the word doing the work is oversight. Most lock-in is not a strategy anybody sat down and chose. It is the shape a product takes when the doors that let people in get built first and the doors that let people out never come up, because the people they matter to are not in the room.
The capability was there the whole time. Every deployed version has been reconstructible from storage since the first deploy, and our own recovery had been reading versions back for months. What was missing was a door, not a capability — which is why this was a small change with a large effect, and why it is written down rather than just shipped.
What leaves, and which call takes it
| what you take | the call | what is true afterwards |
|---|---|---|
| your files and your server code | read_site | text comes back as text, including source files we have no content type for |
| your database | transfer_database | it is in your account, and we have no access to it at all |
| your domain | release_domain | the name is yours to point anywhere |
| the site, off the air | unpublish_site | nothing is deleted; every stored version stays where it was |
read_site gives a listing first and then one file at a time, rather than the whole site in one reply. That is a deliberate trade: the caller is a model that pays for every byte handed to it, and a site is free to be larger than any single answer should be. Two calls to change one file beats a first call that returns a megabyte nobody asked to see.
It also means the assistant reading your site three months from now is not the one that wrote it. That was the third failure the read tool was built for, and the only one with no workaround: a new conversation, the same account, the same site, and a model that could not read one byte of what was already there. Every deploy after that would have been a rewrite.
The database transfer is one-way, and that is the point
After the transfer runs we cannot read your database, cannot back it up, and cannot get it back. That is not a policy we keep. It is a thing we stop being able to do.
Two properties of it are worth naming, because they are the two people have been burned by elsewhere:
- There is no deadline. The door does not close after ninety days, or after
you cancel, or after the account goes quiet.
- A fresh link can be minted whenever it is asked for, however old the
database is. An expired link is not a window you missed.
The second one exists because the first is easy to say and hard to mean. A promise with no deadline that is delivered by a link which expires is a deadline wearing a different hat.
A suspended account can still leave
This is the part that costs something to promise, so it is the part worth checking.
Your stored versions remain stored, because nothing is deleted; they simply stop being served anywhere new.
If we suspend an account for breaching the terms, the gate that decides what that account may do refuses it everything — except six names:
read_siteandlist_deploys, so the code comes outtransfer_databaseandrelease_domain, so the database and the names come outdatabase_statusanddomain_status, so you can see what you have before you take it
Three calls to leave with your things, three to find out what your things are.
It is written as an allowlist rather than a list of what is blocked, and that direction is the whole guarantee. A tool written next year is refused for a suspended account by default, and somebody has to argue it onto that line on purpose. The lazy path keeps the door narrow instead of quietly widening everything else.
Taking your site down is not a support request either
Until recently, every lever here pointed one way. Sites went up. Earlier versions went back up. Nothing let the person who owned a site stop serving it, and the mechanism to do it existed with exactly one caller: an internal sign-in only this company has.
So the only self-service answer to take my shop down was to deploy a page that says closed. That is not the same act. The old page is still stored, still reachable by anyone who kept the URL, and still what a search engine has indexed — and it is a deploy, which is precisely the thing somebody in that moment does not want to be doing.
unpublish_site is the lever. Visitors stop getting the site immediately, nothing is deleted, the site id stays yours, and publishing again puts it back on the version that was live. One thing does not come back on its own: the values of your secrets live on the thing that gets withdrawn, and we cannot read them or copy them, so you set them again once the site is serving. The reply lists them by name.
We would rather name that cost in the tool's own answer than let somebody find it at the worst moment. What each of these tools does and what each one refuses is in the docs.
The half of this that is not built yet
The exit is complete for leaving. It is not complete for what a lot of people will do next.
Take your database out, then move it somewhere else of your own choosing — a different provider, a machine you rent — and today your site cannot reach it again. The repair call exists and it is built for the case where the database is still where we made it. Pointing a site at a database that lives entirely elsewhere is written down as a decision, and that decision is proposed rather than accepted. It has not shipped.
That is the exit door letting you leave with your data and quietly keeping your site, and it is a real gap rather than a hypothetical one. It is being fixed because a promise made out loud has to hold on the far side of the door too, not only up to it.
We are putting it in the post about the exit rather than leaving you to find it on the day it matters.
The rule, once
Everything you put here leaves by a call your assistant can make, with no deadline on it, and being in trouble with us does not close the door. If leaving required us to help, the promise would be worth exactly whatever our mood was on the day you asked.
Drawn from docs/adr/0024-reading-a-site-back.md in this project's own record.