# Cloudflare Workers: your first serverless function

> What Cloudflare Workers are and how to build, run, and deploy your first one. The foundation of the whole Cloudflare developer platform.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-06-20 | Topics: [Cloudflare](https://flaviocopes.com/tags/cloudflare/) | Canonical: https://flaviocopes.com/cloudflare-workers/

I run a few things in production on Cloudflare, and it all starts with the same building block: a Worker.

A **Worker** is a small piece of [JavaScript](https://flaviocopes.com/javascript/) that runs on Cloudflare's servers. There's no server to set up, no machine to keep alive. You write a function, deploy it, and it runs.

The neat part is *where* it runs. Cloudflare has servers all over the world, and your Worker runs on the one closest to whoever is calling it. So it's fast for everyone.

This is the first post in a series where I document the Cloudflare tools I actually use. Everything else, the databases, storage, queues, builds on top of Workers. So let's start here.

## What a Worker looks like

A Worker is a function that takes a request and returns a response.

```js
export default {
  async fetch(request, env, ctx) {
    return new Response('Hello from the edge!')
  },
}
```

That's a complete Worker. When someone hits its URL, the `fetch` function runs and returns the response.

The three arguments matter:

- `request` is the incoming request, a standard `Request` object.
- `env` holds your bindings: databases, storage, secrets. More on those in later posts.
- `ctx` lets you do work after the response is sent, with `ctx.waitUntil()`.

If you've used the [Fetch API](https://flaviocopes.com/fetch-api/) in the browser, this is the same `Request` and `Response`. No new framework to learn.

## Create a project

The fastest way to start is the official scaffolder:

```bash
npm create cloudflare@latest my-worker
```

Pick the "Hello World" Worker when it asks. It sets up the project, installs `wrangler` (Cloudflare's CLI), and creates a `wrangler.jsonc` config file.

Then move into the folder:

```bash
cd my-worker
```

## Run it locally

You don't deploy to test. Cloudflare runs the same engine on your machine:

```bash
npx wrangler dev
```

This starts a local server, usually on `http://localhost:8787`. Open it and you'll see your message. Edit the code, save, and it reloads.

## Read the request

Let's do something with the request. Here we read the path and respond based on it:

```js
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url)

    if (url.pathname === '/') {
      return new Response('Home')
    }

    return new Response('Not found', { status: 404 })
  },
}
```

You can return [JSON](https://flaviocopes.com/json/) just as easily:

```js
return Response.json({ ok: true })
```

## Deploy it

When you're happy, one command puts it live:

```bash
npx wrangler deploy
```

Wrangler uploads your Worker and gives you a URL like `my-worker.your-name.workers.dev`. That's it, your code is running worldwide.

Wondering what this costs once traffic grows? I built a free [Workers cost estimator](https://flaviocopes.com/tools/workers-cost/) that calculates it for Workers, KV, D1, R2 and Durable Objects.

The first time, it'll ask you to log in to your Cloudflare account in the browser.

## What comes next

On its own, a Worker is just a function. The power comes from **bindings**: you attach a database, a storage bucket, a queue, and they show up on that `env` argument.

That's what the rest of this series is about. A database with D1, files with R2, key-value with KV, background jobs with Queues, and more.

But it all starts here, with a function that returns a response.

If you want to read ahead, the [Workers docs](https://developers.cloudflare.com/workers/) are excellent.
