infrasdoc
Cloudflare · Workers · Getting started

Setting up & deploying Cloudflare Workers with Wrangler

A walkthrough for installing dependencies, scaffolding a Worker project, and deploying it — locally and to production — using the Wrangler CLI.

Type Reference Tooling Node.js · npm · Wrangler Audience developers new to Workers
Part 1

Setup guide

From an empty machine to a Worker running in production, in ten steps.

01

Install dependencies

Before creating a Worker project, install the following on your machine:

  • npm — Node's package manager, used to install and run project tooling.
  • Node.js — the JavaScript runtime that npm and Wrangler run on top of.
02

Create a Cloudflare Worker project

bash
npm create cloudflare

Scaffolds a new Cloudflare Worker project, including the base folder structure and starter files.

03

Explore available Wrangler commands

bash
npx wrangler

Lists the commands available in Wrangler, Cloudflare's CLI for building, testing, and deploying Workers.

04

Authenticate with Cloudflare

bash
npx wrangler login

Grants Wrangler access to your Cloudflare account by opening a browser window to complete authentication.

05

Confirm which account you're using

bash
npx wrangler whoami

Verifies which Cloudflare account you're currently logged in with — useful if you manage more than one account.

06

Deploy the project

bash
npm run deploy

Deploys your code to Cloudflare's network. Run this from inside the project directory that holds your deployment files (the folder containing wrangler.toml/wrangler.json and your package.json).

07

Build and test locally

Wrangler lets you build and test your Worker on your machine before pushing it live, so you can catch issues before deployment.

bash
npm start

Starts a local development session so you can preview your Worker at localhost.

08

Edit and hot-reload

Test changes by editing the index.ts file, typically located inside the src directory of your project. Once you save the file, refresh the browser tab and your update should appear.

09

Preview in live mode

While npm start is running, press l on the same page to switch out of local mode and preview how the Worker behaves when it's actually running on Cloudflare's live infrastructure.

  • Open DevTools, go to the Network tab, and click the request for your Worker.
  • Check the Response Headers — you should see a cf-ray header, Cloudflare's unique request identifier for that call.
What you're looking for

The header you're checking for is cf-ray — Cloudflare's per-request trace identifier (Ray ID). Seeing it confirms the request was served by Cloudflare's edge rather than your local dev server.

10

Verify and monitor the deployment

Once npm run deploy finishes, confirm the live version is actually working before you consider the job done:

  • Open the URL returned in your terminal (e.g. https://your-worker.your-subdomain.workers.dev) and confirm it matches what you tested locally.
  • Stream real-time logs from the live Worker to watch for runtime errors:
bash
npx wrangler tail

Leave this running while you exercise the live endpoint — request logs, exceptions, and console.log output stream to your terminal as they happen.

Part 2

Beyond the basics

Project layout, secrets, custom domains, rollbacks, and juggling multiple client accounts.

Project structure

After Step 2, npm create cloudflare scaffolds a project with roughly this layout:

my-worker/
my-worker/
├── src/
│   └── index.ts        # Worker entry point (edited in Step 8)
├── test/               # Sample tests for the Worker
├── wrangler.json       # Wrangler configuration (or wrangler.toml)
├── package.json        # npm scripts and dependencies
└── tsconfig.json       # TypeScript configuration

The two files to know first are src/index.ts, where your Worker's logic lives, and wrangler.json/wrangler.toml, which controls how the project builds and deploys (see toml vs. json below).

Secrets & environment variables

Don't put API keys, tokens, or other sensitive values directly in wrangler.toml/wrangler.json — those files are typically checked into version control. Use secrets instead:

bash
npx wrangler secret put API_KEY

Wrangler prompts you to paste the value, then encrypts and stores it on Cloudflare's side. It's available in your Worker via env.API_KEY but never appears in your source files or config.

Non-sensitive configuration (feature flags, environment names, public URLs) can go in the vars section of your Wrangler config file instead, since those values are fine to commit.

Custom domains & routes

By default, a deployed Worker is reachable at a *.workers.dev subdomain. To serve it from your own domain, attach a route or custom domain in your Wrangler config:

wrangler.json
{
  "routes": [
    { "pattern": "example.com/api/*", "zone_name": "example.com" }
  ]
}

Or, for a dedicated subdomain fully managed by Cloudflare:

wrangler.json
{
  "routes": [
    { "pattern": "api.example.com", "custom_domain": true }
  ]
}

The domain must already be onboarded to Cloudflare (using Cloudflare nameservers) before you can attach a route. Redeploy with npm run deploy after updating the config for the change to take effect.

Rolling back a deployment

If a deployment introduces a regression, you can revert to the previous version without redeploying old code by hand:

bash
npx wrangler rollback

This reverts the live Worker to the last known-good deployment. Use npx wrangler deployments list first if you need to see history and pick a specific version to roll back to.

Managing multiple client projects

Wrangler and npx are directory-aware — they read the wrangler.jsonc (or wrangler.toml) file from whatever directory you're in. That one file defines the project name, D1 bindings, worker entry point, secrets, and every other project-specific setting. There is no global project state. The golden rule: confirm your directory before running any command.

Three commands to run before every session

These take under ten seconds and prevent accidental cross-project changes:

bash
pwd                              # which directory am I in?
cat wrangler.jsonc | grep '"name"'   # does the project match the client?
npx wrangler whoami              # which Cloudflare account is authenticated?
Safe habit

If any of the three outputs doesn't match what you expect, stop and fix the mismatch before continuing. A deploy or database command against the wrong project or account can overwrite production data with no undo.

Switching between client projects

bash
# Move to client A and confirm
cd ~/Projects/client-a
pwd
cat wrangler.jsonc | grep '"name"'
npm run dev              # runs only for client-a

# Switch to client B
cd ~/Projects/client-b
pwd
cat wrangler.jsonc | grep '"name"'
npm run dev              # runs only for client-b

Each directory has its own node_modules, its own wrangler.jsonc, and its own D1 database IDs. Nothing bleeds between projects.

Recommended folder structure

~/Projects/
~/Projects/
  client-a/
    wrangler.jsonc     ← name: "client-a-app"
    src/index.js
    public/index.html
    .dev.vars          ← local secrets (never commit)
    schema.sql
  client-b/
    wrangler.jsonc     ← name: "client-b-app"
    src/index.js
    public/index.html
    .dev.vars
    schema.sql

Each project is self-contained. The .dev.vars file holds secrets for local development only — add it to .gitignore so it's never committed:

bash
echo ".dev.vars" >> .gitignore

Commands that affect production vs. local only

Always confirm your directory and project name before running anything in the left column:

Affects production — confirm firstLocal only — safe anytime
npm run deploynpm run dev
npx wrangler secret put Xnpx wrangler d1 execute … --local
npx wrangler d1 execute … --remotenpx wrangler whoami
npx wrangler d1 create …pwd
npx wrangler rollbackcat wrangler.jsonc

Show the full path in your terminal prompt

Add this to your ~/.zshrc so your current directory is always visible — you can't accidentally run a command in the wrong location:

~/.zshrc
export PS1="%F{green}%~%f %% "

Apply it immediately without restarting your terminal:

bash
source ~/.zshrc

Switching Cloudflare accounts between clients

If different clients use different Cloudflare accounts, log out of the current account and into the correct one before any deployment or database command:

bash
npx wrangler logout
npx wrangler login
npx wrangler whoami

Confirm the account name matches the client before proceeding.

Signing out

Sign out of Wrangler when you finish a session — especially on a shared or temporary machine, or when switching between client Cloudflare accounts:

bash
npx wrangler logout

This revokes the local OAuth token created in Step 4, so the machine no longer has standing access to your Cloudflare account. The token is stored at:

path
~/.wrangler/config/default.toml

After logging out, the next command that requires authentication prompts you to run npx wrangler login again.

When to always log out

Any time you finish a client project before switching to another client's account, before handing a machine to someone else, or at the end of any session on a machine that isn't exclusively yours.

Full account switch sequence

Use this when moving between client accounts to ensure you're always authenticated as the correct user:

bash
npx wrangler logout
cd ~/Projects/client-b
npx wrangler login
npx wrangler whoami

The final whoami confirms the new account is active before you run anything that touches production.

Part 3

Reference

The full command tables, the npm/npx distinction, and troubleshooting notes.

Local development & testing — command reference

All commands below are safe to run locally. None touch your production worker, remote database, or account settings unless the --remote flag is explicitly present.

Starting and stopping the local server

CommandWhat it does
npm run devStarts the local dev server. Worker runs at http://localhost:8787. File changes reload automatically.
npx wrangler devSame as above — direct Wrangler invocation without the npm script.
npx wrangler dev --port 9000Starts the local server on a custom port instead of the default 8787.
npx wrangler dev --localForces fully local mode — local D1, KV, and bindings. No account calls at all.
npx wrangler dev --remoteRuns code locally but bindings (D1, KV, secrets) connect to your real Cloudflare resources.
x while dev runsStops the local dev server cleanly.
r while dev runsForce-reloads the worker without restarting the server.
b while dev runsOpens the local worker URL in your default browser.
d while dev runsOpens Chrome DevTools connected to the local worker.
l while dev runsToggles between local mode and live preview (connected to the edge).

Local D1 database commands

CommandWhat it does
npx wrangler d1 create <db-name>Creates a new D1 database on your account and prints the database_id to add to wrangler.jsonc.
npx wrangler d1 execute <db-name> --local --file=schema.sqlRuns a SQL file against the local D1 database — create tables and seed data for local testing.
npx wrangler d1 execute <db-name> --local --command="…"Runs a one-off SQL query against the local database.
npx wrangler d1 execute <db-name> --remote --file=schema.sqlRuns a SQL file against the production D1 database. Confirm project and account first.
npx wrangler d1 execute <db-name> --remote --command="…"Queries the production database directly. Reads are safe; destructive queries are permanent.
npx wrangler d1 listLists all D1 databases in the current account.
npx wrangler d1 info <db-name>Shows details about a database including ID, region, and size.
Local vs. remote D1

The local D1 database is a separate SQLite file on your machine — changes made with --local don't affect production. Run your schema against both --local and --remote when setting up a new project.

Secrets and environment variables

CommandWhat it does
npx wrangler secret put <KEY>Prompts for a value and stores it as an encrypted secret on the production worker. Available as env.KEY.
npx wrangler secret listLists all secrets on the production worker. Values are never shown — only key names.
npx wrangler secret delete <KEY>Removes a secret from the production worker.
Create .dev.vars in project rootLocal-only secrets. Format: KEY=value per line. Loaded automatically by wrangler dev. Never commit.
.dev.vars
# Example .dev.vars file
ADMIN_PIN=your-local-pin
API_KEY=your-local-api-key
Never commit .dev.vars

Always add .dev.vars to your .gitignore — it contains plaintext secrets for local use only.

bash
echo ".dev.vars" >> .gitignore

Logs and debugging

CommandWhat it does
npx wrangler tailStreams real-time logs from the live production worker — requests, console.log, and exceptions.
npx wrangler tail --format prettySame, but formats output for easier reading in the terminal.
npx wrangler tail --search "keyword"Filters the live log stream to entries containing the keyword.
npx wrangler deployments listLists all past deployments with timestamps and version IDs.

Types and configuration

CommandWhat it does
npx wrangler typesGenerates TypeScript types from your wrangler.jsonc bindings into worker-configuration.d.ts. Run after adding bindings.
npx wrangler whoamiShows the authenticated account name and account ID.
npx wrangler --versionShows the installed Wrangler version.
npm install wrangler@latestUpdates Wrangler to the latest version.

Quick reference — safe vs. production-affecting

Safe — local onlyAffects production — confirm first
npm run devnpm run deploy
npx wrangler dev --localnpx wrangler dev --remote
npx wrangler d1 execute … --localnpx wrangler d1 execute … --remote
npx wrangler whoaminpx wrangler secret put/delete
npx wrangler --versionnpx wrangler rollback
npx wrangler typesnpx wrangler d1 create

NPM vs. NPX

Both ship with Node.js, but they solve different problems: one manages dependencies your project keeps, the other runs tools you don't need to keep.

NPM Node Package Manager

  • Installs and manages project dependencies.
  • Downloads packages permanently into node_modules.

Example: npm install lodash — downloaded permanently into your project's node_modules so you can import it into your code.

NPX Node Package eXecute

  • Executes Node packages and CLI tools directly.
  • Runs packages temporarily, without local or global storage.

Example: npx create-react-app my-app — looks for the tool locally, otherwise temporarily downloads the latest, runs it, then removes it. Your global space stays clean.

Troubleshooting notes

Compatibility date error

Symptom

Wrangler fails to start with an error similar to the block below.

error
The Worker requires compatibility date "xxxx-yy-zz", but the newest
date supported by this server binary is "xxxx-yy-zz".
✘ [ERROR] The Workers runtime failed to start. There was likely a
problem with the workerd binary or your configuration.

Fix: update the compatibility date in your project's Wrangler config file.

  • Open wrangler.json (or wrangler.toml) in your project directory.
  • Update the value: "compatibility_date": "xxxx-yy-zz"
  • Save the file.
  • Restart the local Worker session: npm start

wrangler.toml vs. wrangler.json

FileDescription
wrangler.tomlThe original config format for Workers projects, written in TOML — its own syntax, distinct from (though visually similar to) YAML. Configures your application and references external components (bindings, environment variables, routes, and so on).
wrangler.jsonServes the same purpose as wrangler.toml. Support for the .json extension was added for developers who prefer JSON over TOML.

Critical fields in the Wrangler config file

FieldPurpose
nameThe project name. Can be changed; determines your default *.workers.dev subdomain.
mainThe entry-point file for the project (e.g. src/index.ts).