cf migrate converts a Wrangler project to cf for you. It writes
cloudflare.config.ts from the Wrangler configuration file, adds cf to the
project, and lists the items that you finish by hand. Start with
Migrate a Wrangler project, then use this page to
understand what cf migrate changed or to finish a conversion by hand.
Most Wrangler commands have a cf equivalent, although the command name and
arguments can differ. For example, Worker versions and deployments are under
cf workers versions and cf workers deployments.
To find the cf command for a task, use any of the following:
-
Search: describe the task to
cf cli search, then inspect the match withcf schema:cf cli search "create a D1 database" cf schema d1 create -
Help: add
--helpto a command group, such ascf d1 --help, to list its commands and options. -
Coding agent: ask your agent for the
cfequivalent of a Wrangler command. To set up your agent, refer to Use cf with coding agents.
Resource commands in cf take the identifiers that the Cloudflare API
expects, such as a D1 database ID rather than its name. They act on remote
resources. --local works only for a few resources that local development
provides, such as KV keys, D1 through cf d1 raw, cf d1 migrations list, and
cf d1 migrations apply, and R2 objects. For the full list, refer to
Local resource data. Commands without a
local equivalent, such as cf d1 query, return an error.
cf is in beta, and some Wrangler commands are not supported yet. Run these
with npx wrangler instead of installing Wrangler. Wrangler does not read
cloudflare.config.ts, so pass the Worker name.
-
wrangler tail:cfcannot stream live logs yet. Run:npx wrangler tail <WORKER_NAME> -
wrangler secret put:cfcannot set a single secret yet. Runnpx wrangler secret put <SECRET_NAME> --name <WORKER_NAME>, or upload secrets with a new Worker version by passing--secrets-file <PATH>tocf deployorcf workers versions create.
cf migrate converts Wrangler fields as the following table shows. Worker
settings go under worker in cloudflare.config.ts, and bindings go under
worker.env. A required item is a follow-up that you resolve by hand, as
described in
Resolve follow-up items.
| Wrangler field | cloudflare.config.ts |
Notes |
|---|---|---|
name |
worker.name |
— |
main |
worker.entrypoint |
Written as a string path. You can replace it with a cf-worker import. |
compatibility_date |
worker.compatibilityDate |
— |
compatibility_flags |
worker.compatibilityFlags |
— |
account_id |
accountId |
Top level |
compliance_region |
complianceRegion |
Top level. fedramp_high becomes fedramp-high. |
vars |
bindings.text() or bindings.json() |
Strings use text(). Other values use json(). |
secrets.required |
bindings.secret() |
— |
| KV, D1, R2, Hyperdrive, and other bindings | The matching bindings builder |
Preview resource fields are a required item. |
services |
bindings.worker({ worker }) |
A legacy service environment is a required item. |
queues.producers |
bindings.queue({ name }) |
— |
queues.consumers |
triggers.queue({ name }) |
Consumer settings become camelCase options, such as maxBatchSize. |
Hyperdrive localConnectionString |
dev: { connectionString } on bindings.hyperdrive() |
— |
remote: true on a binding |
dev: { remote: true } |
— |
routes with zone_name |
triggers.fetch({ pattern, zone }) |
— |
routes with zone_id |
triggers.fetch({ pattern, zone }) |
Required item. zone accepts a zone name or a zone ID. |
routes with custom_domain: true |
worker.domains |
— |
triggers.crons |
triggers.scheduled({ schedule }) |
— |
durable_objects.bindings |
bindings.durableObject({ worker, exportName }) |
Required item. Review each binding. |
migrations |
worker.exports |
Not converted. Refer to Convert Durable Object migrations. |
workflows |
bindings.workflow() and exports.workflow() |
Required item. Refer to Workflows. |
containers |
defineContainer() in top-level containers |
Required item. Refer to Containers. |
assets.binding |
bindings.assets() |
— |
assets.html_handling, not_found_handling, run_worker_first |
worker.assets |
Keys become camelCase, such as notFoundHandling. |
assets.directory |
Build settings | Refer to Build settings. |
observability |
worker.observability |
Keys become camelCase, such as headSamplingRate. |
limits |
worker.limits |
Keys become camelCase, such as cpuMs. |
placement |
worker.placement |
— |
tail_consumers |
worker.tailConsumers |
— |
streaming_tail_consumers |
worker.tailConsumers |
Each entry gets streaming: true. |
workers_dev |
worker.workersDev |
— |
preview_urls |
worker.previewUrls |
— |
env.<NAME> |
A case in switch (ctx.mode) |
Refer to Convert environments to modes. |
previews |
A branch on ctx.isPreview |
Required item. Review the branch. |
site |
— | Not supported. Move the site to Workers Static Assets. |
D1 migrations_dir, migrations_pattern, migrations_table |
— | Pass --dir, --pattern, and --table to cf d1 migrations apply. |
build, minify, alias, and other build fields |
Build settings | Refer to Build settings. |
For every field and builder, refer to Programmatic configuration and the Configuration explorer.
Build settings do not go in cloudflare.config.ts. Where they go depends on
the bundler:
| Wrangler field | Vite bundler: vite.config.ts |
Wrangler bundler: wrangler.config.ts |
|---|---|---|
alias |
resolve.alias |
alias |
define |
define |
define |
minify |
build.minify |
minify |
upload_source_maps |
build.sourcemap in the Worker's Vite environment |
uploadSourceMaps |
assets.directory |
publicDir |
assetsDirectory |
build |
Run the command yourself before cf build |
build, with camelCase keys |
dev |
server options |
dev, with camelCase keys |
rules, tsconfig, no_bundle, find_additional_modules, base_dir, preserve_file_names |
Not used. Vite handles module resolution and bundling. | camelCase keys, such as noBundle and baseDir |
With the Wrangler bundler, cf migrate writes these settings to
wrangler.config.ts for you and adds types: { generate: false }. With the
Vite bundler, it lists the fields in a required item for you to move.
wrangler.config.ts is experimental and can change during the beta.
Wrangler environments inherit some top-level fields. cloudflare.config.ts
does not merge environments. It returns one complete configuration for each
mode instead. cf migrate writes a switch (ctx.mode) statement with one
case for each environment. For the generated shape, refer to
Environments.
Replace --env <NAME> with --mode <NAME> on project commands, such as
cf dev, cf build, cf deploy, cf workers versions create, and
cf workers triggers deploy.
Without --mode, the mode depends on the command and the bundler:
| Command | Vite bundler | Wrangler bundler |
|---|---|---|
cf dev |
development |
undefined |
cf build and cf deploy |
production |
undefined |
API commands, such as cf d1 list |
undefined |
undefined |
API commands evaluate cloudflare.config.ts only to read accountId and
complianceRegion. If accountId depends on the mode, a Vite build and an API
command can resolve different accounts. Keep accountId independent of the
mode, or pass the same --mode to every command.
For more information, refer to Modes.
worker.exports replaces the ordered migrations history. cf migrate does
not convert it.
On the first deployment that switches from migrations to worker.exports,
declare every class whose namespace is live today. Use storage: "sqlite" or
storage: "legacy-kv" to match its existing storage.
Do not copy the full migration history. Omit rename and delete operations that have already been applied. If you add them, they become stale tombstones that the deployment reports as safe to remove.
Add a tombstone only for a lifecycle change that has not been applied yet:
Select a highlighted line to show its type and description below it.
export default defineConfig({ (defineConfig reference)
defineConfigFunctionLink to defineConfig
defineConfig<T extends ConfigInput<CloudflareConfig>>(config: T): T;Defines the default export of cloudflare.config.ts. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (isPreview and mode) and returns either.
worker: { (worker reference)
workerOptionalLink to worker
worker?: ConfigInput<WorkerConfig>The Worker defined by this configuration.
name: "orders-api", (name reference)
entrypoint, (entrypoint reference)
entrypointOptionalLink to entrypoint
entrypoint?: string | WorkerModuleThe entrypoint module that will be executed. May be either a path string (e.g. "./src/index.ts") or a module namespace imported with the cf-worker import attribute.
compatibilityDate: "2026-08-24", (compatibilityDate reference)
compatibilityDateRequiredLink to compatibilityDate
compatibilityDate: stringA date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at https://developers.cloudflare.com/workers/configuration/compatibility-dates
exports: { (exports reference)
exportsOptionalLink to exports
exports?: Record<string, Export>Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with exports.durableObject(...). - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at https://developers.cloudflare.com/workers/learning/using-durable-objects. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects. - Construct entries with exports.workflow(...). - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at https://developers.cloudflare.com/workflows/.
Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)
durableObjectBuilderLink to durableObject
durableObject<TContainer extends ContainerDefinition | undefined = undefined>(options: DurableObjectCreatedExportOptions<TContainer>): DurableObjectCreatedExport<TContainer>;Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at https://developers.cloudflare.com/workers/learning/using-durable-objects For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
storageRequiredLink to storage
storage: "sqlite" | "legacy-kv"Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.
OldCounter: exports.durableObject({ (durableObject reference)
durableObjectBuilderLink to durableObject
durableObject(options: DurableObjectRenamedExportOptions): DurableObjectRenamedExport;Rename a provisioned Durable Object namespace's class.
state: "renamed", (state reference)
renamedTo: "Counter", (renamedTo reference)
renamedToRequiredLink to renamedTo
renamedTo: stringThe destination class name. Must be a valid JavaScript identifier and must appear as a live (state: "created") durableObject entry in the same exports map.
UnusedCounter: exports.durableObject({ state: "deleted" }), (durableObject, state reference)
durableObjectBuilderLink to durableObject
durableObject(options: DurableObjectDeletedExportOptions): DurableObjectDeletedExport;Retire a provisioned Durable Object namespace whose class has been removed from code.
Keep a tombstone until a deployment response reports that it is stale, then
remove it. Use cf deploy, rather than a version upload, for a version that
creates, deletes, renames, or transfers a Durable Object class. You cannot roll
back a Durable Object lifecycle change to a version from before the change.
For transfers between Workers and the full list of states, refer to Manage Durable Object lifecycle.
This example finishes the migration of orders-api, the Worker used in
Migrate a Wrangler project. It has a D1 database, a
queue, a cron trigger, a route, and a Durable Object. After cf migrate and
the follow-up steps, cloudflare.config.ts is:
Select a highlighted line to show its type and description below it.
export default defineConfig({ (defineConfig reference)
defineConfigFunctionLink to defineConfig
defineConfig<T extends ConfigInput<CloudflareConfig>>(config: T): T;Defines the default export of cloudflare.config.ts. Pass a configuration object, a promise that resolves to one, or a function that receives the config context (isPreview and mode) and returns either.
accountId: "<ACCOUNT_ID>", (accountId reference)
accountIdOptionalLink to accountId
accountId?: stringThis is the ID of the account associated with your zone. It can also be specified through the CLOUDFLARE_ACCOUNT_ID environment variable.
worker: { (worker reference)
workerOptionalLink to worker
worker?: ConfigInput<WorkerConfig>The Worker defined by this configuration.
name: "orders-api", (name reference)
entrypoint, (entrypoint reference)
entrypointOptionalLink to entrypoint
entrypoint?: string | WorkerModuleThe entrypoint module that will be executed. May be either a path string (e.g. "./src/index.ts") or a module namespace imported with the cf-worker import attribute.
compatibilityDate: "2026-08-24", (compatibilityDate reference)
compatibilityDateRequiredLink to compatibilityDate
compatibilityDate: stringA date in the form yyyy-mm-dd, which will be used to determine which version of the Workers runtime is used. More details at https://developers.cloudflare.com/workers/configuration/compatibility-dates
compatibilityFlags: ["nodejs_compat"], (compatibilityFlags reference)
compatibilityFlagsOptionalLink to compatibilityFlags
compatibilityFlags?: string[]A list of flags that enable features from upcoming features of the Workers runtime, usually used together with compatibilityDate. More details at https://developers.cloudflare.com/workers/configuration/compatibility-flags/
Default: []
env: { (env reference)
envOptionalLink to env
env?: Record<string, Binding>Bindings exposed on the Worker's env object. Construct entries with bindings.kv(...), bindings.r2(...), etc.
ENVIRONMENT: bindings.text("production"), (text reference)
textBuilderLink to text
text<T$1 extends string>(value: T$1): TextBinding<T$1>;Inline string value made available to the Worker on env under the binding name. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
DB: bindings.d1({ (d1 reference)
d1BuilderLink to d1
d1(options?: D1BindingOptions): D1Binding;Binding to a D1 database. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases
name: "orders-db", (name reference)
id: "<DATABASE_ID>", (id reference)
JOBS: bindings.queue<Job>({ name: "orders-jobs" }), (queue, name reference)
queueBuilderLink to queue
queue<TBody = unknown>(options?: QueueBindingOptions): TypedQueueBinding<TBody>;Producer binding to a Cloudflare Queue. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#queues
COUNTERS: bindings.durableObject({ (durableObject reference)
durableObjectBuilderLink to durableObject
durableObject<TWorker$1 extends WorkerReference, TExportName$1 extends DurableObjectExportName<TWorker$1>>(options: DurableObjectBindingOptions<TWorker$1, TExportName$1>): DurableObjectBinding<TWorker$1, TExportName$1>;Binding to a Durable Object class. worker is the name or config of the Worker that defines the class; exportName is the exported class name. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
worker: "orders-api", (worker reference)
workerRequiredLink to worker
worker: TWorker$1The name or config of the Worker that defines the Durable Object class.
exportName: "Counter", (exportName reference)
exportNameRequiredLink to exportName
exportName: TExportName$1The exported class name of the Durable Object.
exports: { (exports reference)
exportsOptionalLink to exports
exports?: Record<string, Export>Configuration for named exports declared by the Worker. Each entry's key is the exported class name; the value configures the export. - Construct entries with exports.durableObject(...). - Declares Durable Object classes exported from this Worker. For more information about Durable Objects, see the documentation at https://developers.cloudflare.com/workers/learning/using-durable-objects. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects. - Construct entries with exports.workflow(...). - Declares Workflows defined by this Worker. For more information about Workflows, see the documentation at https://developers.cloudflare.com/workflows/.
Counter: exports.durableObject({ storage: "sqlite" }), (durableObject, storage reference)
durableObjectBuilderLink to durableObject
durableObject<TContainer extends ContainerDefinition | undefined = undefined>(options: DurableObjectCreatedExportOptions<TContainer>): DurableObjectCreatedExport<TContainer>;Declares a Durable Object class defined by this Worker. For more information about Durable Objects, see the documentation at https://developers.cloudflare.com/workers/learning/using-durable-objects For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
storageRequiredLink to storage
storage: "sqlite" | "legacy-kv"Selects the SQLite-backed storage engine (recommended for new classes). Selects the legacy key-value storage engine.
triggers: [ (triggers reference)
triggersOptionalLink to triggers
triggers?: Trigger[]Event triggers — fetch routes, queue consumers, cron schedules, Email Routing addresses, and raw sockets — that invoke this Worker. Construct entries with triggers.fetch(...), triggers.queue(...), triggers.scheduled(...), triggers.email(...), or triggers.connect(...). For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#triggers
triggers.fetch({ (fetch reference)
fetchBuilderLink to fetch
fetch(options: FetchTriggerOptions): FetchTrigger;Fetch trigger — a route that your Worker should be published to. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes
pattern: "api.example.com/*", (pattern reference)
patternRequiredLink to pattern
pattern: stringA route that your Worker should be published to. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#types-of-routes
zone: "example.com", (zone reference)
zoneOptionalLink to zone
zone?: stringThe DNS zone the pattern is attached to. Required when the pattern is ambiguous.
triggers.queue({ name: "orders-jobs", maxBatchSize: 10 }), (queue, name, maxBatchSize reference)
queueBuilderLink to queue
queue(options: QueueConsumerTriggerOptions): QueueConsumerTrigger;Queue consumer trigger — invokes this Worker when messages arrive on the named queue. For reference, see https://developers.cloudflare.com/workers/wrangler/configuration/#queues
maxBatchSizeOptionalLink to maxBatchSize
maxBatchSize?: numberThe maximum number of messages per batch.
triggers.scheduled({ schedule: "0 * * * *" }), (scheduled, schedule reference)
scheduledBuilderLink to scheduled
scheduled(options: ScheduledTriggerOptions): ScheduledTrigger;Scheduled (cron) trigger — invokes this Worker on the given schedules. More details here https://developers.cloudflare.com/workers/platform/cron-triggers
scheduleRequiredLink to schedule
schedule: stringA "cron" definition to trigger a Worker's "scheduled" function. Lets you call Workers periodically, much like a cron job. More details here https://developers.cloudflare.com/workers/platform/cron-triggers
Compared with the file that cf migrate generates, the finished file:
- Imports the entrypoint with the
cf-workerattribute instead of a string path, so the Worker module exports are typed. - Declares the
Counterclass underexports, replacing themigrationshistory. - Types the queue messages with
bindings.queue<Job>(). - Has no
TODO(@cloudflare)comments orthrowstatement.
To see the generated file, refer to Read the output.