Automate Worker deployments with a simplified SDK and more reliable Terraform provider
We've simplified the programmatic deployment of Workers via our Cloudflare SDKs. This update abstracts away the low-level complexities of the multipart/form-data upload process, allowing you to focus on your code while we handle the deployment mechanics.
This new interface is available in:
- cloudflare-typescript ↗ (4.4.1)
 - cloudflare-python ↗ (4.3.1)
 
For complete examples, see our guide on programmatic Worker deployments.
Previously, deploying a Worker programmatically required manually constructing a multipart/form-data HTTP request, packaging your code and a separate metadata.json file. This was more complicated and verbose, and prone to formatting errors.
For example, here's how you would upload a Worker script previously with cURL:
curl https://api.cloudflare.com/client/v4/accounts/<account_id>/workers/scripts/my-hello-world-script \  -X PUT \  -H 'Authorization: Bearer <api_token>' \  -F 'metadata={        "main_module": "my-hello-world-script.mjs",        "bindings": [          {            "type": "plain_text",            "name": "MESSAGE",            "text": "Hello World!"          }        ],        "compatibility_date": "$today"      };type=application/json' \  -F 'my-hello-world-script.mjs=@-;filename=my-hello-world-script.mjs;type=application/javascript+module' <<EOFexport default {  async fetch(request, env, ctx) {    return new Response(env.MESSAGE, { status: 200 });  }};EOFWith the new SDK interface, you can now define your entire Worker configuration using a single, structured object.
This approach allows you to specify metadata like main_module, bindings, and compatibility_date as clearer properties directly alongside your script content. Our SDK takes this logical object and automatically constructs the complex multipart/form-data API request behind the scenes.
Here's how you can now programmatically deploy a Worker via the cloudflare-typescript SDK ↗
import Cloudflare from "cloudflare";import { toFile } from "cloudflare/index";
// ... client setup, script content, etc.
const script = await client.workers.scripts.update(scriptName, {  account_id: accountID,  metadata: {    main_module: scriptFileName,    bindings: [],  },  files: {    [scriptFileName]: await toFile(Buffer.from(scriptContent), scriptFileName, {      type: "application/javascript+module",    }),  },});import Cloudflare from 'cloudflare';import { toFile } from 'cloudflare/index';
// ... client setup, script content, etc.
const script = await client.workers.scripts.update(scriptName, {  account_id: accountID,  metadata: {    main_module: scriptFileName,    bindings: [],  },  files: {    [scriptFileName]: await toFile(Buffer.from(scriptContent), scriptFileName, {      type: 'application/javascript+module',    }),  },});View the complete example here: https://github.com/cloudflare/cloudflare-typescript/blob/main/examples/workers/script-upload.ts ↗
We've also made several fixes and enhancements to the Cloudflare Terraform provider ↗:
- Fixed the 
cloudflare_workers_script↗ resource in Terraform, which previously was producing a diff even when there were no changes. Now, yourterraform planoutputs will be cleaner and more reliable. - Fixed the 
cloudflare_workers_for_platforms_dispatch_namespace↗, where the provider would attempt to recreate the namespace on aterraform apply. The resource now correctly reads its remote state, ensuring stability for production environments and CI/CD workflows. - The 
cloudflare_workers_route↗ resource now allows for thescriptproperty to be empty, null, or omitted to indicate that pattern should be negated for all scripts (see routes docs). You can now reserve a pattern or temporarily disable a Worker on a route without deleting the route definition itself. - Using 
primary_location_hintin thecloudflare_d1_database↗ resource will no longer always try to recreate. You can now safely change the location hint for a D1 database without causing a destructive operation. 
We've also properly documented the Workers Script And Version Settings in our public OpenAPI spec and SDKs.
Was this helpful?
- Resources
 - API
 - New to Cloudflare?
 - Directory
 - Sponsorships
 - Open Source
 
- Support
 - Help Center
 - System Status
 - Compliance
 - GDPR
 
- Company
 - cloudflare.com
 - Our team
 - Careers
 
- © 2025 Cloudflare, Inc.
 - Privacy Policy
 - Terms of Use
 - Report Security Issues
 - Trademark