---
title: Deploy a Worker
description: In this tutorial, you will follow step-by-step instructions to deploy a Hello World application using Cloudflare Workers and Pulumi infrastructure as code (IaC).
image: https://edgetunnel-b2h.pages.dev/core-services-preview.png
---

> Documentation Index  
> Fetch the complete documentation index at: https://edgetunnel-b2h.pages.dev/pulumi/llms.txt  
> Use this file to discover all available pages before exploring further. 

[Skip to content](#%5Ftop) 

# Deploy a Worker

In this tutorial, you will follow step-by-step instructions to deploy a Hello World application using Cloudflare Workers and Pulumi infrastructure as code (IaC) to familiarize yourself with the resource management lifecycle. In particular, you will create a Worker, a Route, and a DNS Record to access the application before cleaning up all the resources.

Note

You will provision resources that qualify under free tier offerings for both Pulumi Cloud and Cloudflare.

## Before you begin

Ensure you have:

* A Cloudflare account and API Token with permission to edit the resources in this tutorial. If you need to, sign up for a [Cloudflare account ↗](https://www.cloudflare.com/sign-up) before continuing. Your token must have the following:  
  * `Account-Workers Scripts-Edit` permission
  * `Zone-Workers Route-Edit` permission
  * `Zone-DNS-Edit` permission
* A Pulumi Cloud account. You can sign up for an [always-free individual tier ↗](https://app.pulumi.com/signup).
* The [Pulumi CLI](https://edgetunnel-b2h.pages.dev/pulumi/installing/) is installed on your machine.
* A [Pulumi-supported programming language ↗](https://github.com/pulumi/pulumi?tab=readme-ov-file#languages) configured. (TypeScript, JavaScript, Python, Go, .NET, Java, or use YAML)
* A Cloudflare-managed domain. Complete the [Add a site tutorial](https://edgetunnel-b2h.pages.dev/pulumi/tutorial/add-site/) to bring your existing domain under Cloudflare.

## 1\. Initialize your project

A Pulumi project is a collection of files in a dedicated folder that describes the infrastructure you want to create. The Pulumi project folder is identified by the required `Pulumi.yaml` file. You will use the Pulumi CLI to create and configure a new project.

### a. Create a directory

Use a new and empty directory for this tutorial.

```sh
mkdir serverless-cloudflare
cd serverless-cloudflare
```

### b. Login to Pulumi Cloud

[Pulumi Cloud ↗](https://www.pulumi.com/product/pulumi-cloud/) is a hosted service that provides a secure and scalable platform for managing your infrastructure as code. You will use it to store your Pulumi backend configurations.

At the prompt, press Enter to log into your Pulumi Cloud account via the browser. Alternatively, you may provide a [Pulumi Cloud access token ↗](https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/).

```sh
pulumi login
```

### c. Create a new program

A Pulumi program is code written in a [supported programming language ↗](https://github.com/pulumi/pulumi?tab=readme-ov-file#languages) that defines infrastructure resources.

To create a program, select your language of choice and run the `pulumi` command:

* [  JavaScript ](#tab-panel-10387)
* [  TypeScript ](#tab-panel-10388)
* [  Python ](#tab-panel-10389)
* [ go ](#tab-panel-10390)
* [ Java ](#tab-panel-10391)
* [ .NET ](#tab-panel-10392)
* [ YAML ](#tab-panel-10393)

```sh
pulumi new javascript --name serverless-cloudflare --yes
# wait a few seconds while the project is initialized
```

```sh
pulumi new typescript --name serverless-cloudflare --yes
# wait a few seconds while the project is initialized
```

```sh
pulumi new python --name serverless-cloudflare --yes
# wait a few seconds while the project is initialized
```

```sh
pulumi new go --name serverless-cloudflare --yes
# wait a few seconds while the project is initialized
```

```sh
pulumi new java --name serverless-cloudflare --yes
# wait a few seconds while the project is initialized
```

```sh
pulumi new csharp --name serverless-cloudflare --yes
# wait a few seconds while the project is initialized
```

```sh
pulumi new yaml --name serverless-cloudflare --yes
```

### d. Create a stack

A Pulumi [stack ↗](https://www.pulumi.com/docs/concepts/stack/) is an instance of a Pulumi program. Stacks are independently configurable and may represent different environments (development, staging, production) or feature branches. For this tutorial, you'll use the `dev` stack.

To instantiate your `dev` stack, run:

```sh
pulumi up --yes
# wait a few seconds for the stack to be instantiated.
```

You have not defined any resources at this point, so you'll have an empty stack.

### e. Save your application settings

In this step, you will store your application settings in a Pulumi [ESC Environment ↗](https://www.pulumi.com/docs/esc/environments/), a YAML file containing configurations and secrets. These can be accessed in several ways, including a Pulumi program. All ESC Environments securely reside in your Pulumi Cloud account and can be fully managed via the Pulumi CLI. For this tutorial, you will store the following values:

* Your Cloudflare [account ID](https://edgetunnel-b2h.pages.dev/fundamentals/account/find-account-and-zone-ids/).
* A valid Cloudflare API [token](https://edgetunnel-b2h.pages.dev/fundamentals/api/get-started/create-token/).
* A domain. For instance, `example.com`.

```sh
# Give your new ESC Environment a name
E=hello-world/dev-env


# Initialize the new ESC Environment
pulumi config env init --env $E --yes
```

```sh
Creating environment hello-world/dev-env for stack dev...
```

```sh
# Replace abc123 with your Cloudflare account ID
pulumi env set $E --plaintext pulumiConfig.accountId abc123


# Replace API_TOKEN with your Cloudflare API token
pulumi env set $E --secret pulumiConfig.cloudflare:apiToken API_TOKEN


# Replace example.com with your domain
pulumi env set $E --plaintext pulumiConfig.domain example.com
```

### f. Install the Cloudflare package

You need to install the Cloudflare package for your language of choice in order to define Cloudflare resources in your Pulumi program.

Install the Cloudflare package by running the following command:

* [  JavaScript ](#tab-panel-10394)
* [  TypeScript ](#tab-panel-10395)
* [  Python ](#tab-panel-10396)
* [ go ](#tab-panel-10397)
* [ Java ](#tab-panel-10398)
* [ .NET ](#tab-panel-10399)
* [ YAML ](#tab-panel-10400)

```sh
npm install @pulumi/cloudflare
```

```sh
added 1 package ...
```

```sh
npm install @pulumi/cloudflare
```

```sh
added 1 package ...
```

```sh
echo "pulumi_cloudflare>=5.38,<6.0.0" >> requirements.txt
source venv/bin/activate
pip install -r requirements.txt
```

```sh
...Collecting pulumi-cloudflare...
```

```sh
go get github.com/pulumi/pulumi-cloudflare/sdk/v3/go/cloudflare
```

```sh
go: downloading github.com/pulumi/pulumi-cloudflare ...
```

Below are Apache Maven instructions. For other Java project managers such as Gradle, see the official [Maven repository ↗](https://central.sonatype.com/artifact/com.pulumi/cloudflare/overview)

1. Open your `pom.xml` file.
2. Add the Pulumi Cloudflare dependency inside the `<dependencies>` section.

```xml
<dependency>
    <groupId>com.pulumi</groupId>
    <artifactId>cloudflare</artifactId>
    <version>5.38.0</version>
</dependency>
```

1. Run:

```sh
mvn clean install
```

```sh
...[INFO] BUILD SUCCESS...
```

```sh
dotnet add package Pulumi.Cloudflare
```

```sh
...
info : Adding PackageReference for package 'Pulumi.Cloudflare' into project
...
```

There are no dependencies to download for YAML. Skip ahead.

## 2\. Define Cloudflare resources in code

With the Cloudflare package installed, you can now define any [supported Cloudflare resource ↗](https://www.pulumi.com/registry/packages/cloudflare/) in your Pulumi program. Next, define a Worker, a Route, and a DNS Record.

### a. Add a Workers script

The [Workers Script resource ↗](https://www.pulumi.com/registry/packages/cloudflare/api-docs/workersscript/) represents a Cloudflare Worker that can be deployed to the Cloudflare network.

Replace the contents of your entrypoint file with the following:

* [  JavaScript ](#tab-panel-10401)
* [  TypeScript ](#tab-panel-10402)
* [  Python ](#tab-panel-10403)
* [ go ](#tab-panel-10404)
* [ Java ](#tab-panel-10405)
* [ .NET ](#tab-panel-10406)
* [ YAML ](#tab-panel-10407)

**Filename: `index.js`**

**JavaScript**

```javascript
"use strict";
const pulumi = require("@pulumi/pulumi");
const cloudflare = require("@pulumi/cloudflare");


const config = new pulumi.Config();
const accountId = config.require("accountId");
const domain = config.require("domain");


const content = `export default {
  async fetch(request) {
    const options = { headers: { 'content-type': 'text/plain' } };
    return new Response("Hello World!", options);
  },
};`;


const worker = new cloudflare.WorkersScript("hello-world-worker", {
  accountId: accountId,
  name: "hello-world-worker",
  content: content,
  module: true, // ES6 module
});
```

**Filename: `index.ts`**

**TypeScript**

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as cloudflare from "@pulumi/cloudflare";


const config = new pulumi.Config();
const accountId = config.require("accountId");
const domain = config.require("domain");


const content = `export default {
  async fetch(request) {
    const options = { headers: { 'content-type': 'text/plain' } };
    return new Response("Hello World!", options);
  },
};`;


const worker = new cloudflare.WorkersScript("hello-world-worker", {
  accountId: accountId,
  name: "hello-world-worker",
  content: content,
  module: true, // ES6 module
});
```

**Filename: `__main__.py`**

**Python**

```python
"""Pulumi program """
import pulumi
import pulumi_cloudflare as cloudflare


CONFIG = pulumi.Config()
ACCOUNT_ID = CONFIG.get("accountId")
DOMAIN = CONFIG.require("domain")
CONTENT = """
export default {
  async fetch(request) {
    const options = { headers: { 'content-type': 'text/plain' } };
    return new Response("Hello World!", options);
  },
};
"""


worker = cloudflare.WorkersScript("hello-world-worker",
    account_id=ACCOUNT_ID,
    name="hello-world-worker",
    content=CONTENT,
    module=True  # ES6 module
)
```

**Filename: `main.go`**

```go
package main


import (
  "github.com/pulumi/pulumi-cloudflare/sdk/v5/go/cloudflare"
  "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
  "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)


func main() {
  pulumi.Run(func(ctx *pulumi.Context) error {
    conf := config.New(ctx, "")
    accountID := conf.Get("accountId")
    domain := conf.Get("domain")
    content := `
    export default {
      async fetch(request) {
        const options = { headers: { 'content-type': 'text/plain' } };
        return new Response("Hello World!", options);
      },
    };
    `
    worker, err := cloudflare.NewWorkersScript(ctx, "hello-world-worker", &cloudflare.WorkersScriptArgs{
      AccountId: pulumi.String(accountID),
      Name:      pulumi.String("hello-world-worker"),
      Content:   pulumi.String(content),
      Module:    pulumi.Bool(true), // ES6 module
    })
    if err != nil {
      return err
    }


    return nil
  })
}
```

**Filename: `src/main/java/myproject/App.java`**

```java
package myproject;


import com.pulumi.Pulumi;
import com.pulumi.cloudflare.WorkersScript;
import com.pulumi.cloudflare.WorkersScriptArgs;
import com.pulumi.core.Output;


public class App {
    public static void main(String[] args) {
        Pulumi.run(ctx -> {
            var content = """
              export default {
                async fetch(request) {
                  const options = { headers: { 'content-type': 'text/plain' } };
                  return new Response("Hello World!", options);
                },
              };
            """;


            var accountId = ctx.config().require("accountId");
            var domain = ctx.config().require("domain");
            var worker = new WorkersScript("hello-world-worker", WorkersScriptArgs.builder()
                .accountId(accountId)
                .name("hello-world-worker")
                .content(content)
                .module(true)
                .build());


            return;
        });
    }
}
```

**Filename: `Program.cs`**

```csharp
using Pulumi;
using Cloudflare = Pulumi.Cloudflare;


return await Deployment.RunAsync(() =>
{
    var config = new Config();
    var accountId = config.Require("accountId");
    var domain = config.Require("domain");
    var content = @"
            export default {
                async fetch(request) {
                    const options = { headers: { 'content-type': 'text/plain' } };
                    return new Response(""Hello World!"", options);
                },
            };
        ";


    var worker = new Cloudflare.WorkersScript("hello-world-worker", new()
    {
        AccountId = accountId,
        Name = "hello-world-worker",
        Content = content,
        Module = true
    });
    return;
});
```

**Filename: `Pulumi.yaml`**

**YAML**

```yaml
name: serverless-cloudflare
runtime: yaml
resources:
  worker:
    type: cloudflare:WorkersScript
    properties:
      accountId: "${accountId}"
      name: "hello-world-worker"
      content: |
        export default {
            async fetch(request) {
                const options = { headers: { 'content-type': 'text/plain' } };
                return new Response("Hello World!", options);
            },
        };
      module: true
```

### b. Add a Route

You will now add a [Workers Route resource ↗](https://www.pulumi.com/registry/packages/cloudflare/api-docs/workersroute/) to your Pulumi program so the Workers script can have an endpoint and be active. To properly configure the Route, you will also look up the zone ID for your domain.

Add the following code snippet to your entrypoint file **after** the Worker script resource:

* [  JavaScript ](#tab-panel-10408)
* [  TypeScript ](#tab-panel-10409)
* [  Python ](#tab-panel-10410)
* [ go ](#tab-panel-10411)
* [ Java ](#tab-panel-10412)
* [ .NET ](#tab-panel-10413)
* [ YAML ](#tab-panel-10414)

**Filename: `index.js`**

**JavaScript**

```javascript
const zone = cloudflare.getZone({
  accountId: accountId,
  name: domain,
});


const zoneId = zone.then((z) => z.zoneId);


const route = new cloudflare.WorkersRoute("hello-world-route", {
  zoneId: zoneId,
  pattern: "hello-world." + domain,
  scriptName: worker.name,
});
```

**Filename: `index.ts`**

**TypeScript**

```typescript
const zone = cloudflare.getZone({
  accountId: accountId,
  name: domain,
});


const zoneId = zone.then((z) => z.zoneId);


const route = new cloudflare.WorkersRoute("hello-world-route", {
  zoneId: zoneId,
  pattern: "hello-world." + domain,
  scriptName: worker.name,
});
```

**Filename: `__main__.py`**

**Python**

```python
zone = cloudflare.get_zone(account_id=ACCOUNT_ID, name=DOMAIN)
zone_id = zone.zone_id
route = cloudflare.WorkersRoute("hello-world-route",
    zone_id=zone_id,
    pattern="hello-world." + DOMAIN,
    script_name=worker.name
)
```

**Filename: `main.go`**

```go
zone, err := cloudflare.LookupZone(ctx, &cloudflare.LookupZoneArgs{
  AccountId: &accountID,
  Name:      &domain,
}, nil)
if err != nil {
  return err
}


route, err := cloudflare.NewWorkersRoute(ctx, "hello-world-route", &cloudflare.WorkersRouteArgs{
  ZoneId:     pulumi.String(zone.Id),
  Pattern:    pulumi.String("hello-world." + domain),
  ScriptName: worker.Name,
})
if err != nil {
  return err
}
```

**Filename: `src/main/java/myproject/App.java`**

```java
final var zone = CloudflareFunctions.getZone(GetZoneArgs.builder()
  .accountId(accountId)
  .name(domain)
  .build());
var route = new WorkersRoute("hello-world-route", WorkersRouteArgs.builder()
  .zoneId(zone.applyValue(getZoneResult -> getZoneResult.id()))
  .pattern("hello-world." + domain)
  .scriptName(worker.name())
  .build());
```

**Filename: `Program.cs`**

```csharp
var zone = Output.Create(Cloudflare.GetZone.InvokeAsync(new()
{
    AccountId = accountId,
    Name = domain,
}));
var route = new Cloudflare.WorkersRoute("hello-world-route", new()
{
    ZoneId = zone.Apply(z => z.Id),
    Pattern = "hello-world." + domain,
    ScriptName = worker.Name,
});
```

**Filename: `Pulumi.yaml`**

Below the `runtime` key, add the following code:

**YAML**

```yaml
# new top-level section
variables:
  zone:
    fn::invoke:
      function: cloudflare:getZone
      arguments:
        accountId: ${accountId}
        name: ${domain}
```

Below the `worker` resource, add the following code:

**YAML**

```yaml
route:
  type: cloudflare:WorkersRoute
  properties:
    zoneId: ${zone.id}
    pattern: "hello-world.${domain}"
    scriptName: ${worker.name}
```

### c. Add a DNS Record

You will now add a DNS [Record resource ↗](https://www.pulumi.com/registry/packages/cloudflare/api-docs/record/) to resolve the previously configured Route. In the next step, you'll also output the Route URL so it can be easily accessed.

Add the following code snippet to your entrypoint file **after** the Route resource:

* [  JavaScript ](#tab-panel-10415)
* [  TypeScript ](#tab-panel-10416)
* [  Python ](#tab-panel-10417)
* [ go ](#tab-panel-10418)
* [ Java ](#tab-panel-10419)
* [ .NET ](#tab-panel-10420)
* [ YAML ](#tab-panel-10421)

**Filename: `index.js`**

**JavaScript**

```javascript
const record = new cloudflare.Record("hello-world-record", {
  name: route.pattern,
  type: "A",
  content: "192.0.2.1",
  zoneId: zoneId,
  proxied: true,
});


exports.url = pulumi.interpolate`https://${record.hostname}`;
```

**Filename: `index.ts`**

**TypeScript**

```typescript
const record = new cloudflare.Record("hello-world-record", {
  name: route.pattern,
  type: "A",
  content: "192.0.2.1",
  zoneId: zoneId,
  proxied: true,
});


export const url = pulumi.interpolate`https://${record.hostname}`;
```

**Filename: `__main__.py`**

**Python**

```python
record = cloudflare.Record("hello-world-record",
    name=route.pattern,
    type="A",
    content="192.0.2.1",
    zone_id=zone_id,
    proxied=True
)


url = pulumi.Output.concat("https://", record.hostname)
pulumi.export('url', url)
```

**Filename: `main.go`**

```go
record, err := cloudflare.NewRecord(ctx, "hello-world-record", &cloudflare.RecordArgs{
  Name:    route.Pattern,
  Type:    pulumi.String("A"),
  Content: pulumi.String("192.0.2.1"),
  ZoneId:  pulumi.String(zone.Id),
  Proxied: pulumi.Bool(true),
})
if err != nil {
  return err
}


ctx.Export("url", pulumi.Sprintf("https://%s", record.Hostname))
```

**Filename: `src/main/java/myproject/App.java`**

```java
var record = new Record("hello-world-record", RecordArgs.builder()
    .name(route.pattern())
    .type("A")
    .content("192.0.2.1")
    .zoneId(zone.applyValue(getZoneResult -> getZoneResult.id()))
    .proxied(true)
    .build());


ctx.export("url", Output.format("https://%s", record.hostname()));
```

**Filename: `Program.cs`**

Notice the updated ' return ' statement because you're now exporting a value. Ensure that you also include `using System.Collections.Generic;` in your imports.

```csharp
var record = new Cloudflare.Record("hello-world-record", new()
{
    Name = route.Pattern,
    Type = "A",
    Content = "192.0.2.1",
    ZoneId = zone.Apply(z => z.Id),
    Proxied = true
});


return new Dictionary<string, object?>
{
    ["url"] = Output.Format($"https://{record.Hostname}")
};
```

Notice the new top-level `outputs` section.

**YAML**

```yaml
  record:
    type: cloudflare:Record
    properties:
      name: ${route.pattern}
      type: A
      content: "192.0.2.1"
      zoneId: ${zone.id}
      proxied: true


outputs:
  url: "https://${record.hostname}"
```

Note

You may need to use `http` instead depending on your domain settings.

### d. (Optional) Verify your code

Confirm all your changes match the full solution below:

* [  JavaScript ](#tab-panel-10422)
* [  TypeScript ](#tab-panel-10423)
* [  Python ](#tab-panel-10424)
* [ go ](#tab-panel-10425)
* [ Java ](#tab-panel-10426)
* [ .NET ](#tab-panel-10427)
* [ YAML ](#tab-panel-10428)

**Filename: `index.js`**

**JavaScript**

```javascript
"use strict";
const pulumi = require("@pulumi/pulumi");
const cloudflare = require("@pulumi/cloudflare");


const config = new pulumi.Config();
const accountId = config.require("accountId");
const domain = config.require("domain");


const content = `export default {
  async fetch(request) {
    const options = { headers: { 'content-type': 'text/plain' } };
    return new Response("Hello World!", options);
  },
};`;


const worker = new cloudflare.WorkersScript("hello-world-worker", {
  accountId: accountId,
  name: "hello-world-worker",
  content: content,
  module: true, // ES6 module
});


const zone = cloudflare.getZone({
  accountId: accountId,
  name: domain,
});


const zoneId = zone.then((z) => z.zoneId);


const route = new cloudflare.WorkersRoute("hello-world-route", {
  zoneId: zoneId,
  pattern: "hello-world." + domain,
  scriptName: worker.name,
});


const record = new cloudflare.Record("hello-world-record", {
  name: route.pattern,
  type: "A",
  content: "192.0.2.1",
  zoneId: zoneId,
  proxied: true,
});


exports.url = pulumi.interpolate`https://${record.hostname}`;
```

**Filename: `index.ts`**

**TypeScript**

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as cloudflare from "@pulumi/cloudflare";


const config = new pulumi.Config();
const accountId = config.require("accountId");
const domain = config.require("domain");


const content = `export default {
  async fetch(request) {
    const options = { headers: { 'content-type': 'text/plain' } };
    return new Response("Hello World!", options);
  },
};`;


const worker = new cloudflare.WorkersScript("hello-world-worker", {
  accountId: accountId,
  name: "hello-world-worker",
  content: content,
  module: true, // ES6 module
});


const zone = cloudflare.getZone({
  accountId: accountId,
  name: domain,
});


const zoneId = zone.then((z) => z.zoneId);


const route = new cloudflare.WorkersRoute("hello-world-route", {
  zoneId: zoneId,
  pattern: "hello-world." + domain,
  scriptName: worker.name,
});


const record = new cloudflare.Record("hello-world-record", {
  name: route.pattern,
  type: "A",
  content: "192.0.2.1",
  zoneId: zoneId,
  proxied: true,
});


export const url = pulumi.interpolate`https://${record.hostname}`;
```

**Filename: `__main__.py`**

**Python**

```python
"""Pulumi program """
import pulumi
import pulumi_cloudflare as cloudflare


CONFIG = pulumi.Config()
ACCOUNT_ID = CONFIG.get("accountId")
DOMAIN = CONFIG.require("domain")
CONTENT = """
export default {
  async fetch(request) {
    const options = { headers: { 'content-type': 'text/plain' } };
    return new Response("Hello World!", options);
  },
};
"""


worker = cloudflare.WorkersScript("hello-world-worker",
    account_id=ACCOUNT_ID,
    name="hello-world-worker",
    content=CONTENT,
    module=True  # ES6 module
)


zone = cloudflare.get_zone(account_id=ACCOUNT_ID, name=DOMAIN)
zone_id = zone.zone_id
route = cloudflare.WorkersRoute("hello-world-route",
    zone_id=zone_id,
    pattern="hello-world." + DOMAIN,
    script_name=worker.name
)


record = cloudflare.Record("hello-world-record",
    name=route.pattern,
    type="A",
    content="192.0.2.1",
    zone_id=zone_id,
    proxied=True
)


url = pulumi.Output.concat("https://", record.hostname)
pulumi.export('url', url)
```

**Filename: `main.go`**

```go
package main


import (
  "github.com/pulumi/pulumi-cloudflare/sdk/v5/go/cloudflare"
  "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
  "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)


func main() {
  pulumi.Run(func(ctx *pulumi.Context) error {
    conf := config.New(ctx, "")
    accountID := conf.Get("accountId")
    domain := conf.Get("domain")
    content := `
    export default {
      async fetch(request) {
        const options = { headers: { 'content-type': 'text/plain' } };
        return new Response("Hello World!", options);
      },
    };
    `
    worker, err := cloudflare.NewWorkersScript(ctx, "hello-world-worker", &cloudflare.WorkersScriptArgs{
      AccountId: pulumi.String(accountID),
      Name:      pulumi.String("hello-world-worker"),
      Content:   pulumi.String(content),
      Module:    pulumi.Bool(true), // ES6 module
    })
    if err != nil {
      return err
    }
    zone, err := cloudflare.LookupZone(ctx, &cloudflare.LookupZoneArgs{
      AccountId: &accountID,
      Name:      &domain,
    }, nil)
    if err != nil {
      return err
    }


    route, err := cloudflare.NewWorkersRoute(ctx, "hello-world-route", &cloudflare.WorkersRouteArgs{
      ZoneId:     pulumi.String(zone.Id),
      Pattern:    pulumi.String("hello-world." + domain),
      ScriptName: worker.Name,
    })
    if err != nil {
      return err
    }


    record, err := cloudflare.NewRecord(ctx, "hello-world-record", &cloudflare.RecordArgs{
      Name:    route.Pattern,
      Type:    pulumi.String("A"),
      Content: pulumi.String("192.0.2.1"),
      ZoneId:  pulumi.String(zone.Id),
      Proxied: pulumi.Bool(true),
    })
    if err != nil {
      return err
    }


    ctx.Export("url", pulumi.Sprintf("https://%s", record.Hostname))


    return nil
  })
}
```

**Filename: `src/main/java/myproject/App.java`**

```java
package myproject;


import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.cloudflare.WorkersScript;
import com.pulumi.cloudflare.WorkersScriptArgs;
import com.pulumi.cloudflare.CloudflareFunctions;
import com.pulumi.cloudflare.inputs.GetZoneArgs;
import com.pulumi.cloudflare.WorkersRoute;
import com.pulumi.cloudflare.WorkersRouteArgs;
import com.pulumi.cloudflare.Record;
import com.pulumi.cloudflare.RecordArgs;


public class App {
    public static void main(String[] args) {
        Pulumi.run(ctx -> {
            var content = """
        export default {
          async fetch(request) {
            const options = { headers: { 'content-type': 'text/plain' } };
            return new Response("Hello World!", options);
          },
        };
      """;


            var accountId = ctx.config().require("accountId");
            var domain = ctx.config().require("domain");


            var worker = new WorkersScript("hello-world-worker", WorkersScriptArgs.builder()
                .accountId(accountId)
                .name("hello-world-worker")
                .content(content)
                .module(true)
                .build());
            final var zone = CloudflareFunctions.getZone(GetZoneArgs.builder()
                .accountId(accountId)
                .name(domain)
                .build());
            var route = new WorkersRoute("hello-world-route", WorkersRouteArgs.builder()
                .zoneId(zone.applyValue(getZoneResult -> getZoneResult.id()))
                .pattern("hello-world." + domain)
                .scriptName(worker.name())
                .build());
            var record = new Record("hello-world-record", RecordArgs.builder()
                .name(route.pattern())
                .type("A")
                .content("192.0.2.1")
                .zoneId(zone.applyValue(getZoneResult -> getZoneResult.id()))
                .proxied(true)
                .build());


            ctx.export("url", Output.format("https://%s", record.hostname()));
            return;
        });
    }
}
```

**Filename: `Program.cs`**

```csharp
using System.Collections.Generic;
using Pulumi;
using Cloudflare = Pulumi.Cloudflare;


return await Deployment.RunAsync(() =>
{
    var config = new Config();
    var accountId = config.Require("accountId");
    var domain = config.Require("domain");
    var content = @"
            export default {
                async fetch(request) {
                    const options = { headers: { 'content-type': 'text/plain' } };
                    return new Response(""Hello World!"", options);
                },
            };
        ";


    var worker = new Cloudflare.WorkersScript("hello-world-worker", new()
    {
        AccountId = accountId,
        Name = "hello-world-worker",
        Content = content,
        Module = true
    });
    var zone = Output.Create(Cloudflare.GetZone.InvokeAsync(new()
    {
        AccountId = accountId,
        Name = domain,
    }));
    var route = new Cloudflare.WorkersRoute("hello-world-route", new()
    {
        ZoneId = zone.Apply(z => z.Id),
        Pattern = "hello-world." + domain,
        ScriptName = worker.Name,
    });


    var record = new Cloudflare.Record("hello-world-record", new()
    {
        Name = route.Pattern,
        Type = "A",
        Content = "192.0.2.1",
        ZoneId = zone.Apply(z => z.Id),
        Proxied = true
    });


    return new Dictionary<string, object?>
    {
        ["url"] = Output.Format($"https://{record.Hostname}")
    };
});
```

**Filename: `Pulumi.yaml`**

**YAML**

```yaml
name: serverless-cloudflare
runtime: yaml
variables:
  zone:
    fn::invoke:
      function: cloudflare:getZone
      arguments:
        accountId: ${accountId}
        name: ${domain}


resources:
  worker:
    type: cloudflare:WorkersScript
    properties:
      accountId: "${accountId}"
      name: "hello-world-worker"
      content: |
        export default {
            async fetch(request) {
                const options = { headers: { 'content-type': 'text/plain' } };
                return new Response("Hello World!", options);
            },
        };
      module: true
  route:
    type: cloudflare:WorkersRoute
    properties:
      zoneId: ${zone.id}
      pattern: "hello-world.${domain}"
      scriptName: ${worker.name}
  record:
    type: cloudflare:Record
    properties:
      name: ${route.pattern}
      type: A
      content: "192.0.2.1"
      zoneId: ${zone.id}
      proxied: true


outputs:
  url: "https://${record.hostname}"
```

## 3\. Deploy your application

Now that you have defined all the Cloudflare resources, you can deploy the Hello World application to your Cloudflare account using the Pulumi CLI.

To deploy the changes, run:

```sh
pulumi up --yes
```

```sh
wait for the dev stack to become ready
```

## 4\. Test the Worker

You incrementally added Cloudflare resources to run and access your Hello World application. You can test your application by curling the `url` output from the Pulumi stack.

```sh
curl $(pulumi stack output url)
```

```sh
Hello, World!
```

## 5\. Clean up

In this last step, you will clean up the resources and stack used throughout the tutorial.

### a. Delete the Cloudflare resources

```sh
pulumi destroy
```

### b. Remove the Pulumi stack

```sh
pulumi stack rm dev
```

## Next steps

Visit the [Cloudflare package documentation ↗](https://www.pulumi.com/docs/reference/pkg/cloudflare/) to explore other resources you can define with Pulumi and Cloudflare.

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://edgetunnel-b2h.pages.dev/pulumi/tutorial/hello-world/#page","headline":"Deploy a Worker · Pulumi docs","description":"In this tutorial, you will follow step-by-step instructions to deploy a Hello World application using Cloudflare Workers and Pulumi infrastructure as code (IaC).","url":"https://edgetunnel-b2h.pages.dev/pulumi/tutorial/hello-world/","inLanguage":"en","image":"https://edgetunnel-b2h.pages.dev/core-services-preview.png","dateModified":"2025-10-13","publisher":{"@type":"Organization","name":"Cloudflare","url":"https://www.cloudflare.com/"},"isPartOf":{"@type":"WebSite","@id":"https://edgetunnel-b2h.pages.dev/#website","name":"Cloudflare Docs","url":"https://edgetunnel-b2h.pages.dev/"},"keywords":["JavaScript","TypeScript","Python","Go","Java",".NET","YAML"]}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"/directory/","name":"Directory"}},{"@type":"ListItem","position":2,"item":{"@id":"/pulumi/","name":"Pulumi"}},{"@type":"ListItem","position":3,"item":{"@id":"/pulumi/tutorial/","name":"Tutorials"}},{"@type":"ListItem","position":4,"item":{"@id":"/pulumi/tutorial/hello-world/","name":"Deploy a Worker"}}]}
```
