Skip to content
downpipes docs

Leaving downpipes: a controlled exit you can prove

Leaving downpipes is a sequence you run, not a button you press. There is deliberately no one-click exit and no automated tear-down command. The exit is a short, documented workflow composed from surfaces you already use day to day, and you run it yourself, because nothing about your backups is held by the vendor and so there is no vendor offboarding to wait on.

This page is for the self-hoster winding the product down, whether to move to something else or to retire a project. It assembles the exit from the surfaces that already exist: a final backup you prove recoverable, evidence you capture off-account, and the deprovisioning that removes the engine and every way the people who could reach it still can. The point of doing it as a sequence rather than a single action is that each step leaves you something you can show afterwards, so the exit is one you can prove rather than one you merely assert.

There is no guided exit checklist in the product today. This page documents the order to do the steps in; the console does not walk you through them as one flow. Each step is its own surface, linked below, and you decide when to move to the next.

Why there is no vendor offboarding to wait on

The reason the exit is yours to run is the reason the rest of the product works the way it does. Your backups already live in the destination you chose, the engine runs in your own Cloudflare account, and the vendor holds no Cloudflare token, no destination credential, and no dashboard seat. There is no vendor-held copy of your data to request back and no vendor system to be removed from. So leaving is not a request you file; it is a sequence you execute, and the evidence you keep is evidence you produced.

That also means the timeline is yours. You can take the final backup, prove it, capture the evidence, and only then remove the engine, with no dependency on a support queue and no window during which the vendor still holds something.

Step one: take a final backup and prove it is recoverable

Do not just stop the backups; take a last one and prove it can be restored before you tear anything down. Proving recoverability is the difference between an exit you can stand behind and a folder of files you hope are good.

  1. Take a final run

    Let the last scheduled run complete, or trigger one from the downpipe so the newest good run reflects the estate as it stands at exit. The Runs view is where you confirm it landed: a stopped or failed backup is loud there, and the newest good run is the recovery point you will prove (RunsView, console/src/screens/runs/view.ts).

  2. Drill the run, or dry-run a restore

    Open the final run in the Runs view and run a drill against it. A passing drill verifies the recorded records and, where the posture allows, restores a sample, and the console records dated drill evidence best-effort so a recoverability trail exists (openRunDetail and the drill action, console/src/screens/runs/detail.ts). The drill is an Operator-or-higher action; a dry-run restore stays available to your role, so a Viewer can still build a restore plan to confirm the run is addressable.

  3. Read the verdict honestly

    A passing drill is your recoverability proof for the exit. If the engine is in the break-glass-only posture it returns the documented “could not complete” outcome rather than a pass, because the drill reopens a run the engine sealed earlier and that posture holds no in-account read-back key; that is an expected result, not a fault (renderDrill, console/src/screens/runs/detail.ts). It is not the end of the road, and you do not have to reach for a terminal. Two proofs stay open to you in the console. A keyless attestation needs no decryption key at all and proves the run is signed, complete and not rolled back. An attended verification under Restore proves more: you supply your break-glass key in your own browser, your engine decrypts the in-scope archives while you watch, and the key is forgotten when the session ends. A full attended pass is what stamps “restorability last proven”, which is the artefact worth having on an exit. Any other failed drill is a real problem to investigate before you rely on the archive.

For the full account of how recoverability is proven, including the offline path for the break-glass posture, see prove recoverability and the runs and history view.

Step two: capture evidence off-account

With a proven recovery point, capture the evidence that documents the state of the estate at exit and keep it somewhere the engine’s removal cannot touch. Three artefacts matter, and they come from two surfaces.

Download the support bundle. Any signed-in role can download the redaction-safe diagnostics bundle from Settings. It aggregates the engine version and provenance, presence-only status, the preflight report, per-downpipe run-history rows, notification delivery outcomes, and the licence tier, and it never contains a key, a secret value, or your data (buildSupportBundle, engine/src/admin/support.ts; renderSupportBundle, console/src/screens/settings.ts). It is a snapshot of how the estate was configured and how it ran, useful as an exit record even though its primary purpose is support.

Export the audit log. From the Access and security screen, export the tamper-evident, hash-chained audit log as JSON or CSV. The export includes the chain head hash, so an external party can later confirm nothing was truncated (runAuditExport, console/src/screens/access-security/audit.ts). This is the who-did-what record for the life of the engine, and exporting it before you decommission preserves it beyond the engine’s own retention cap.

Keep the downloaded key files. The recovery kit you downloaded during the key ceremony, the key files that let you open the archives, is yours to keep offline. Signing out and removing the engine do not delete those files from your disk; they remain, and they are what makes the archives recoverable after downpipes is gone (renderOffboarding sign-out copy, console/src/screens/settings/sections.ts). Store them where you store the rest of your break-glass material.

Treat the audit export and the support bundle as tamper-evident evidence: the audit chain lets an external party detect truncation or alteration because every entry is hashed with the one before it. Detectable is the claim, not impossible to alter. Keep the exported head hash with the export so the chain can be checked against it later.

A practical note on order: capture the evidence before you remove anyone or anything. Once roles are removed and the engine is gone, the surfaces that produce these artefacts are gone too.

Step three: deprovision the engine and the people

Only now remove access and the engine itself. This is three distinct jobs, and the console does one of them.

Remove in-app roles via the member-removal ceremony. On the Roles and access tab, use Remove on each member’s row to strip their in-app role. This is the single removal ceremony every entry point routes through; it is immediate, audited, and bumps the engine session epoch so the person’s engine sessions stop working on their next request (openOffboardModal, console/src/screens/access-security/roles-members.ts). The engine refuses to remove the last Owner, so promote or remove in an order that leaves the guard satisfied until you are ready to decommission.

Remove people in your own IdP and Cloudflare Access. This is the step the console cannot do for you. The console never holds a credential for your identity provider or for Cloudflare Access, so removing a person there is an action you complete in your own dashboard; the console guides it and records that you did it, but it cannot perform it (openOffboardModal copy and the responsibility rows, console/src/screens/access-security/roles-members.ts). A removed in-app role does not end a Cloudflare Access session at the edge: until you remove the person in your IdP or end their Access session, they can still pass your Access policy. The per-member detail of this boundary is on offboarding a member.

Revoke the ways each person signs in to the engine. Removing a role and removing them from your IdP still leave three engine-side stores standing: the passkey credential they enrolled, any unconsumed recovery codes they banked, and any invite issued to them and never redeemed. All three sit behind Cloudflare Access rather than in front of it, so neither the IdP removal nor ending an Access session reaches them, and each is a way back in for anyone who re-passes your Access policy. The Roles and access tab carries this under Sign-in factors (who can still sign in): it lists every email that can still authenticate, states a verdict per row, and Revoke sign-in clears all three stores for that email as one audited act. The same routes are on the admin API (GET /admin/signin-factors, POST /admin/signin-factors/revoke) for anyone scripting a wind-down. It matters most if you are removing people while leaving the engine standing; if you are decommissioning the Workers in the same sitting, removing the deployment removes the stores with it. Both routes, their guards and why they are separate from a role removal are on offboarding a member.

Remove the Workers. Decommissioning the engine and console Workers is a Cloudflare-side action you take in your own account, not a console switch; the console cannot delete the deployment that serves it. The detailed decommissioning runbook lives in offboarding and exit, which covers retiring the deployment alongside the access removal described here.

Residency at exit: your data does not move

A reassurance worth stating plainly: retiring downpipes does not move your data. Your backups already live in the destination you chose, an in-account R2 bucket or an S3-compatible store, and that destination is yours and stays exactly where it is when the engine goes away (residencyBody, console/src/screens/settings/sections.ts). Removing the Workers removes the thing that wrote the archives; it does not remove the archives.

So the archives you proved recoverable in step one remain in your destination after step three, openable with the key files you kept in step two. That is the whole point of a no-custody design at exit: there is no vendor-held copy to retrieve and no migration of your data away from a vendor, because the data was never with the vendor. For exactly where the ciphertext and the metadata sit, see data residency.

Where this fits

The exit is assembled from surfaces that each have their own page; this one is the order to use them in.

The recoverability proof

Step one rests on the drill and dry-run restore in the Runs view, and on the keyless attestation and attended verification for the break-glass-only posture. See prove recoverability and the runs and history view.

The evidence artefacts

Step two produces the support bundle and the audit export. See the support bundle for what the bundle contains and the audit log for the chain and the export.

The deprovisioning detail

Step three removes roles, the sign-in factors, identity, and the Workers. See offboarding a member for the per-member ceremony, the sign-in-factor revoke and the IdP boundary, and offboarding and exit for the full decommissioning runbook.

Because nothing is vendor-held, the exit is yours to run and yours to evidence. Start at the runs and history view to take and prove the final backup, capture the support bundle and the audit log, then work through the deprovisioning on offboarding and exit. The support model that explains why none of this waits on a vendor is getting support without giving us access.

Last updated .