Workers Expands Beyond JavaScript With New Language Templates

Cloudflare Workers is no longer limited to JavaScript and WebAssembly-compiling languages like Rust, C, and C++. The platform now supports Python, Scala, Kotlin, Reason, and Dart, with ready-made templates that get you from zero to a published Worker in minutes.

Each language has a corresponding GitHub template. Install wrangler, generate a project from the template for your language of choice, follow the README setup instructions, and run wrangler publish. For Python, that looks like:

wrangler generate my-python-project https://github.com/cloudflare/python-worker-hello-world

After publishing, your Worker is live on your workers.dev subdomain. A free Workers account is all you need to get started.

How the Language Support Works

The key constraint for any language targeting Workers is producing a single JavaScript file within the 1MB bundle size limit. For memory-managed languages, compiling to JavaScript is generally the right path. Libraries that depend on native code or language-specific VM features won't translate, though WebAssembly remains an option for those cases until the garbage collection story for WebAssembly matures.

Two examples — one dynamically typed and one statically typed — illustrate the template design and how you can extend the approach to additional languages.

Python and Transcrypt

The Python template relies on Transcrypt, a Python-to-JavaScript compiler. The runtime adds roughly 70k to the bundle, well within platform limits.

Transcrypt by default emits multiple JS and source map files into a __target__ directory. Wrangler's built-in webpack support, paired with the transcrypt-loader npm package, handles bundling everything into a single output file. The project's webpack.config.js shows the setup.

The Worker code itself is mostly familiar Python. Dictionary literals replace JavaScript objects, and lambda stands in for anonymous arrow functions. The addEventListener call is not a Python built-in — it's part of the Workers runtime exposed in global scope. Because Python is dynamically typed, you don't need type signatures for JavaScript APIs, but errors surface at runtime rather than at compile time. Transcrypt does offer experimental static checking via mypy if you want earlier feedback.

Scala and Scala.js

The Scala template uses Scala.js, which compiles Scala to JavaScript through the sbt build tool. Setup requires only sbt and a JDK. Running sbt fullOptJS produces a single index.js at the project root where Wrangler expects it, after which wrangler publish deploys as usual.

Scala.js uses the Google Closure Compiler for size optimization during fullOptJS. The hello world compiles to 14k; a more realistic project with async fetch is around 100k, well within Workers limits. Existing Scala type signatures for fetch and service worker APIs are available. The entry point, Main.scala, imports scala.scalajs.js to access JavaScript type equivalents like js.Array and js.Dictionary. The Worker structure mirrors a TypeScript hello world, with Scala's Unit instead of Void and square brackets instead of angle brackets for type parameters.

Worker-specific extensions to standard JavaScript APIs require type definitions when using a statically typed language. You can either convert the existing TypeScript type definitions for Workers automatically or write signature stubs yourself. The Globals.scala example shows manual signatures with the @js.native annotation, indicating the implementation lives in existing JavaScript. The @JSGlobalScope annotation marks functions as available in the JavaScript global scope, matching how addEventListener is used in a plain JavaScript Worker. You have flexibility in type strictness, from generic signatures like def addEventListener(any: Any*): Any to fully typed ones like js.Function1[FetchEvent, Unit].

Workers KV and Asynchronous Code in Scala

A more realistic example shows how Scala templates handle Workers KV and async operations. The project is a simple HTTP API storing and retrieving text values keyed by path components, with usage like PUT /meaning of life/42 or GET /meaning of life/.

KV API type signatures are defined in Globals.scala. The KVNamespace interface becomes a Scala trait annotated with @js.native. The needed methods are string-based versions of KV.get and KV.put, with return values wrapped in js.Promise since they're asynchronous. A type alias keeps the option open to handle array or stream return types later.

For async handling, the code converts between js.Promise and Scala Future using toJSPromise and toFuture from js.JSConverters. The put function uses map to transform the stored value into a Response and recover to handle failures. If you prefer async/await syntax, scala-async is an alternative. Pattern matching in the request handler makes the code concise and robust, matching exactly on the desired HTTP method and path combinations while defaulting to an informative error.

Contributing New Language Templates

The template approach is designed to be extensible. Pull requests for hello world projects or more complex examples in other languages are welcome. RedMonk's latest language rankings show Python as the first non-Java or JavaScript language to place in the top two, underscoring the demand for broader language options on the platform.