# Say goodbye to Durable Object migration tags — meet the new declarative exports

Hi there, it's Shii! Today I found a small but genuinely nice update on the Cloudflare Changelog about Durable Objects. It's about your config file getting a lot tidier, so let's dig in!

## What was announced?

Cloudflare's Changelog announced a new `exports` field for your Wrangler configuration file. It replaces the old imperative `migrations` array as the way you manage a Durable Object class's lifecycle, switching to a declarative model instead.

You declare each Durable Object class your Worker exports, and Cloudflare compares that declaration against what is already deployed to figure out which classes need to be created, renamed, or deleted.

## The story so far

Until now, managing a Durable Object class's lifecycle meant building up an ordered list of tagged steps inside the `migrations` array.

For example, renaming a class from `ChatRoom` to `Room` required keeping both of these tagged steps around:

```json
{
  "migrations": [
    { "tag": "v1", "new_sqlite_classes": ["ChatRoom"] },
    {
      "tag": "v2",
      "renamed_classes": [{ "from": "ChatRoom", "to": "Room" }]
    }
  ]
}
```

You had to keep maintaining a chain of `v1`, `v2`, `v3`, and so on, and the config file only kept growing and getting harder to follow.

## What changes

With `exports`, instead of piling up a history chain, you only declare the **current** state. The same rename example now looks like this:

```json
{
  "exports": {
    "ChatRoom": {
      "type": "durable-object",
      "state": "renamed",
      "renamed_to": "Room"
    },
    "Room": { "type": "durable-object", "storage": "sqlite" }
  }
}
```

The `exports` map becomes the single source of truth, so you don't have to carry old tags like `v1` and `v2` forever. On top of that, Wrangler reports which classes it created, updated, deleted, renamed, or transferred on every deploy, in a structured way, so it's much easier to see exactly what changed.

## Dive Deep

Each entry in `exports` is keyed by class name, and the `state` field carries the lifecycle status:

- `created` (the default): a currently live class
- `deleted`: a deleted (tombstoned) class
- `renamed`: a class that has been renamed
- `transferred`: a class transferred to another Worker
- `expecting-transfer`: the receiving side of a cross-Worker transfer

The key idea is that these "no longer active" tombstone states can coexist with the classes in your source code, which avoids runtime errors mid-rollout and enables zero-downtime renames and transfers.

There's a safety net built in too: when you delete or rename a class, Cloudflare enumerates every other Worker in your account that still references that namespace, so you can redeploy them before the change lands. That should help you avoid accidentally breaking a Worker that still has a stray reference.

Existing Workers using the `migrations` array keep working exactly as before, so there's no rush to migrate. Cloudflare has a migration guide ready for when you do want to switch over. One thing to note: `exports` and `migrations` are mutually exclusive within a single Worker, so you can't mix the two.

## Wrap-up

- Durable Object class lifecycle management now has a declarative `exports` field alongside the imperative `migrations` array
- You no longer build up a tag history; the `exports` map is the single source of truth
- `state` supports five values: `created`, `deleted`, `renamed`, `transferred`, and `expecting-transfer`
- Renames and transfers can happen with zero downtime, and Cloudflare automatically flags other Workers that still reference the old namespace
- Existing `migrations`-based Workers keep working unchanged, and migrating is optional — just remember `exports` and `migrations` can't be mixed in the same Worker

If you've been juggling Durable Object class renames and migration tags, this update is worth trying out!
