# Durable Objects: the config pairing

A Durable Object needs two config entries that reference the same class name, and they serve different purposes. Getting one without the other is the classic deploy failure.

## 1. The binding: how your Worker reaches the class

```toml
[[durable_objects.bindings]]
name = "MY_DO"
class_name = "MyDurableObject"
```

`name` is what your code uses (`env.MY_DO.get(...)`); `class_name` must match the exported class in your Worker code.

## 2. The migration: how the runtime learns the class exists

```toml
[[migrations]]
tag = "v1"
new_sqlite_classes = [ "MyDurableObject" ]
```

The tag must be unique per entry. New classes go in `new_sqlite_classes`: Cloudflare recommends the SQLite storage backend for all new Durable Object namespaces, and creating new namespaces with the old key-value backend is no longer supported for accounts without an existing KV-backed namespace. SQLite-backed objects expose `ctx.storage.sql` in the constructor.

## The failure mode

Deploying the binding without the migration (or with a reused tag) produces class-not-found behavior at runtime. Both entries, same class name, unique tag, every time you add a class.

## Checklist

- Export the class from your Worker entrypoint module; the runtime looks it up by `class_name`.
- Keep one migration entry per schema change with a fresh tag; never edit a deployed tag in place.
- Use the SQLite API (`ctx.storage.sql`) for new code, not the legacy KV storage API.