Docs / Serverless Objects / Porting from Cloudflare

Port a Cloudflare Workers project

Move an existing Wrangler project to Serverless Objects: config preflight rules, bindings, migrations, testing and what to check before switching traffic.

Serverless Objects runs applications through an engine (celld today). It does not implement the Workers runtime itself. Treat Cloudflare's API as the contract, and check each binding and API your project uses against the compatibility tables.

1. Use a supported Wrangler config

The CLI reads wrangler.json or wrangler.jsonc in the project root. celld's deploy path does not read wrangler.toml, so convert it first. Declare the bindings and Durable Object migrations the Worker actually uses.

The preflight validates top-level keys instead of passing unknown settings through:

Key Behavior
Unknown or unsupported keys Fail preflight. Remove or translate them; don't assume a Wrangler setting has a celld equivalent.
observability, upload_source_maps Removed with a warning. celld does not implement them.
build.command Runs before celld starts. Other build options are rejected.
assets.directory Must be explicit, unless the project uses @cloudflare/vite-plugin: then vite build runs and the output is discovered. Discovery needs exactly one candidate containing index.html.
{
  "name": "my-worker",
  "main": "src/index.js",
  "compatibility_date": "2026-02-24",
  "durable_objects": {
    "bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
  },
  "migrations": [{ "tag": "v1", "new_sqlite_classes": ["Counter"] }]
}

Migrations

SQLite-backed Durable Object classes require new_sqlite_classes. celld 0.6 supports only the tag and new_sqlite_classes migration fields. Class rename, deletion and transfer migrations are rejected.

Compatibility date

Set a compatibility date appropriate for the APIs your app uses. deleteAll() clearing a pending alarm was tested with 2026-02-24 or later.

2. Configure bindings and storage

Use bindings celld supports, and provide provider credentials through the environment or credential chain. celld's upstream list includes Durable Objects, KV, D1, R2, Queues and Workflows, but the conformance run does not cover every binding. Workers AI, Vectorize, Hyperdrive, Browser Rendering and Email Workers are not provided.

For state that must survive a node restart, configure the bucket in sobjects.toml. That is separate from project bindings. Don't put credentials in either the Wrangler config or sobjects.toml.

3. Run and test

sobjects dev ./my-worker
sobjects deploy ./my-worker

dev delegates to celld's local development server and does not start the ingress. deploy uses the configured celld bucket and endpoint, or explicit flags. For traffic from outside the host, run the node with TLS ingress, and keep celld, its operator API and the admin API on loopback. See running as a service.

Use Wrangler's local runtime as a reference and run the same app on celld. The conformance suite does this for its own apps. Passing it is useful evidence, not a claim of complete Workers parity.

4. Check portability for the native engine

If you plan to run on the native engine, check that the app stays portable to Cloudflare:

sobjects build ./my-worker --strict

build lists each Node.js built-in the app imports and whether Cloudflare's nodejs_compat supports it. --strict exits 1 if the app is native-only.

5. Review application assumptions

Before switching traffic, check for:

  • APIs or bindings celld does not implement, or features the current suite doesn't exercise.
  • Cloudflare-only configuration fields, deployment hooks, observability and source-map upload.
  • Assumptions about production networking, service bindings, outbound connections, Cache or global coordination.
  • Durable Object migrations beyond adding SQLite classes.
  • WebSocket behavior across a cell move, facets and cross-isolate RPC. These need separate verification.
  • Whether the app has been run through the sobjects CLI itself. A minimal Agents SDK app has run through sobjects deploy and sobjects up; the official samples, chat agents, MCP and Workflows have not.

Don't infer production Cloudflare behavior from local Wrangler results, or full celld compatibility from one passing sample. Record any mismatch as a conformance case.