Skip to docs content
Browse documentation
On this page

Finish the migration

When a new way replaces an old one, the work isn't done until the old way is gone.

When a new way replaces an old one, the migration isn't finished until the old way is deleted. Don't run two lanes indefinitely. Look for the leftovers: compatibility shims, aliases, unused settings, old tables, and doc sentences that only exist to explain the old name.

If the old way can't go yet (a second deploy has to land first, say), record a cleanup task with a clear "ready when" condition in the same change. A code comment isn't a tracker.

Example

Package sql() storage moved from Postgres to per-package SQLite databases in Durable Objects. That happened in two steps. First a release removed every code path that read the old tables. Then, once nothing used them, a separate migration dropped them:

DROP TABLE "org_sql_storage" CASCADE;
DROP TABLE "package_sql_storage" CASCADE;

The drop shipped on its own because it can't be undone (see Two-way and one-way doors ). The same pass removed the old cron endpoint, its shared secret, and the Node and Docker deployment.

In your packages

When you replace an export or change a storage key, move the callers and remove the old export in the same version. If stored data has to be converted, do it once with a job, check it, then delete the conversion code.