RPC and SQLite storage

Configure SQLite-backed objects

Bind the class, add a newsqliteclasses migration, export it, and initialize a small schema safely.

Every Durable Object class needs two things in configuration. A namespace binding, so Workers can reach it. And a migration entry, so the platform knows the class exists and which storage backend it uses. New objects should use the SQLite backend through new_sqlite_classes.

Start with the class. Extend DurableObject from cloudflare:workers and create the schema in the constructor:

import { DurableObject } from 'cloudflare:workers'

export class ProjectRoom extends DurableObject {
  constructor(ctx, env) {
    super(ctx, env)
    ctx.blockConcurrencyWhile(async () => {
      this.ctx.storage.sql.exec(`
        create table if not exists messages (
          id integer primary key autoincrement,
          author text not null,
          body text not null,
          created_at integer not null
        )
      `)
    })
  }
}

blockConcurrencyWhile holds every incoming event until the callback finishes. No request can see a half-created schema. Use it only for short setup like this. Never make a network request inside it: a slow or hanging fetch in there freezes every request to the object.

Then wire the class up in wrangler.jsonc:

{
  "durable_objects": {
    "bindings": [
      { "name": "PROJECT_ROOM", "class_name": "ProjectRoom" }
    ]
  },
  "migrations": [
    { "tag": "v1", "new_sqlite_classes": ["ProjectRoom"] }
  ]
}

The binding says “give Workers an env.PROJECT_ROOM namespace backed by the ProjectRoom class”. The migration says “this class is new, provision it on the SQLite backend”.

Forget the migration and wrangler deploy rejects the Worker. It tells you the new class must be added to a migration. That’s the most common first-deploy stumble, and the fix is exactly this v1 entry.

Two details that bite

The class_name must match the exported class name character for character. A typo like ProjectRooms deploys nothing useful.

And the storage backend is permanent for a namespace. You can’t flip an existing class between backends with a config edit. That’s why new classes should start on SQLite.

Try the setup end to end: create a ProjectRoom class, add its binding and migration, run wrangler types, and check that the exported class name matches the configuration. If wrangler deploy succeeds and the typed env.PROJECT_ROOM namespace shows up in your editor, the plumbing is right.

Lesson completed