How to Build a Python Worker on Cloudflare with FastAPI
Learn how to build and deploy a FastAPI application as a Cloudflare Python Worker, from local setup and dependencies to production deployment.
On this page
Cloudflare made Python Workers generally available on September 21, 2026, turning what had been an experimental runtime into a supported way to deploy Python applications on Workers. The practical change is bigger than simply replacing JavaScript with Python: Python Workers can now use frameworks such as FastAPI and Flask, package dependencies through pyproject.toml, and connect to Cloudflare services such as D1, R2, Workers AI, and Durable Objects. This tutorial builds a small FastAPI application locally, tests it, and deploys it as a Python Worker.
What changed with Python Workers GA
Python Workers run Python through Pyodide, a version of CPython compiled to WebAssembly, inside Cloudflare's V8 isolate environment. Cloudflare's current tooling uses pywrangler to create projects, manage Python dependencies, run local development, and deploy Workers. The important distinction from a conventional Python server is that you are not deploying a long-running process such as Gunicorn or Uvicorn onto a virtual machine. The Worker runtime receives the request and invokes your Python application inside Cloudflare's execution environment.
The general-availability release also removes much of the friction that previously made Python Workers interesting mainly for experimentation. Cloudflare documents support for ASGI applications such as FastAPI and Starlette and WSGI applications such as Flask and Django. Python Workers can also access Cloudflare bindings from Python, so an application can combine a Python request handler with services such as D1 without adding a separate JavaScript layer.
Install uv and prepare the Python project
The current Python Workers workflow is built around uv, a Python package and environment manager. Before creating the Worker, make sure Python and Node.js are available on your development machine, then install or enable uv according to your operating system. You do not need to install a separate traditional Python web server because Cloudflare's Worker tooling supplies the runtime integration needed by the application.
Once uv is available, create a new Python Worker with the Cloudflare CLI:
uvx --from workers-py pywrangler initThe initializer creates the project configuration and a pyproject.toml file. When it asks for a template, choose a basic Python Worker if you want to follow the example directly, or a framework-oriented template when the available templates match your application. The important result is a project that uses workers-py as its development tooling rather than treating Python as a conventional server process.
Add FastAPI as the web framework
FastAPI is a Python framework for building HTTP APIs using Python type hints and an ASGI interface. ASGI, or Asynchronous Server Gateway Interface, is the standard interface that lets an asynchronous Python web framework communicate with its server runtime. In a normal FastAPI deployment, that server is often Uvicorn. Python Workers provide the ASGI integration directly, so you do not need to run a separate Uvicorn process inside the Worker.
Open the generated pyproject.toml and add FastAPI to the project's dependencies. A minimal configuration looks like this:
[project]
name = "my-python-worker"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"fastapi"
]
[dependency-groups]
dev = [
"workers-py",
"workers-runtime-sdk"
]The dependency declaration matters because pywrangler uses the project configuration when it bundles Python packages for deployment. Cloudflare's current documentation says Python Workers support pure Python and PyEmscripten-compatible packages, along with packages included in Pyodide. That does not mean every package on PyPI will work unchanged, especially packages that depend on native extensions that do not have a compatible WebAssembly build.
Create the FastAPI request handler
Now create src/main.py and put the FastAPI application in it. The application can remain almost identical to a small FastAPI service you would run elsewhere; the important difference is how the Worker connects the application to the runtime.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello from Python Workers"}At this point, app is an ordinary FastAPI application. It defines one HTTP route and returns a Python dictionary that FastAPI converts into a JSON response. You have not created a listening socket, selected a port, or started Uvicorn because those responsibilities belong to the Worker runtime.
Connect FastAPI to the Worker runtime
The missing piece is the ASGI entrypoint. Python Workers expose an ASGI adapter that connects an ASGI application such as FastAPI to the Worker request lifecycle. Add the adapter after creating the application.
from fastapi import FastAPI
from workers import asgi
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello from Python Workers"}
Default = asgi.entrypoint(app)This final line is what turns the FastAPI application into the entrypoint Cloudflare can execute. Without it, you have a valid FastAPI application but have not connected it to the Worker request interface. Cloudflare's FastAPI documentation specifically uses this ASGI integration rather than asking developers to run a conventional Python application server.
Run the Python Worker locally
Start the development server from the project directory:
uv run pywrangler devThe command starts a local Workers runtime rather than a conventional FastAPI development server. Open the address printed by the command and request the root route. You should receive a JSON response containing "Hello from Python Workers". This test confirms three separate pieces at once: the Python project can be loaded, FastAPI can be imported, and the ASGI adapter can connect the framework to the Workers runtime.
Add a real API endpoint before deploying
A useful next test is an endpoint that accepts structured input rather than returning a fixed message. FastAPI's request models provide a simple way to check that JSON parsing and response serialization work correctly inside the Worker.
from fastapi import FastAPI
from pydantic import BaseModel
from workers import asgi
app = FastAPI()
class Greeting(BaseModel):
name: str
@app.get("/")
def read_root():
return {"message": "Python Worker is running"}
@app.post("/greet")
def greet(data: Greeting):
return {"message": f"Hello, {data.name}"}
Default = asgi.entrypoint(app)Run the development server again and send a JSON request to /greet. A request containing a name should produce a JSON response containing the corresponding greeting. This small endpoint is worth testing before deployment because it exercises the framework's validation layer as well as the Worker integration instead of proving only that a static route responds.
Understand what gets deployed
When you run the deployment command, pywrangler packages your Python code and declared dependencies and sends them to the Workers platform. Cloudflare then validates the Python application, initializes the Python runtime, and creates a snapshot of the initialized WebAssembly memory so expensive initialization work can happen during deployment rather than repeatedly during requests.
That execution model is different from keeping a Python process alive on a server. The Worker is designed around request handling inside an isolate, and the deployment process prepares the runtime so incoming requests can start from an initialized state. This is one reason Python code that assumes unrestricted access to the operating system, local files, native sockets, or arbitrary background processes cannot simply be moved to Workers unchanged.
Deploy the FastAPI Worker
Once the local endpoint works, deploy the application with the Python Workers CLI:
uv run pywrangler deployThe deployment command uploads the Worker and its supported dependencies and publishes it to your Cloudflare account. After deployment, use the generated Worker address to call the same / and /greet routes you tested locally. A successful response from both routes gives you a useful comparison between local execution and the deployed Worker rather than relying only on a successful deployment message.
If deployment fails while resolving a dependency, check that package before changing your application. Cloudflare's supported-package model is tied to Python packages that can run in its WebAssembly-based environment. A package can be perfectly valid on ordinary CPython and still require changes or a compatible wheel before it can run inside a Python Worker.
Connect the API to Cloudflare services when the basic version works
The real advantage of running Python on Workers appears when the application needs Cloudflare's platform services. Python Workers can access bindings for services including D1, R2, Durable Objects, Queues, Workers AI, and other parts of the platform. For example, a D1 database binding is exposed through the Worker's environment and can be queried from Python without creating a separate database server.
That makes the migration path fairly direct: first prove that the Python request handler works, then add one binding at a time. A database-backed API should be tested with a development database or another deliberately isolated resource rather than pointing the first experiment at production data. The same principle applies to object storage, queues, and AI services because the Worker code may be correct while the environment configuration is not.
Know where Python Workers fit and where they do not
Python Workers are a useful fit for HTTP APIs, lightweight web applications, framework-based endpoints, and Python services that benefit from Cloudflare's global runtime and bindings. They are less straightforward when an application depends heavily on native CPython extensions, unrestricted operating-system access, long-running processes, or assumptions about a conventional server filesystem. Those constraints are properties of the execution model, not bugs that can be solved by changing the FastAPI route.
The safest way to move an existing application is therefore incremental. Start with one endpoint, confirm its dependencies work under the Worker runtime, connect one Cloudflare binding, and then move the next piece. The fact that FastAPI, Flask, Django, and other Python frameworks can now plug into Python Workers means you can preserve much more of an existing application's structure, but it does not make every Python package or server architecture portable without changes.
Use the deployment result as your compatibility test
A successful Python Worker is not simply one that returns "Hello World." The stronger test is a small FastAPI application that installs its dependencies, runs under the local Worker runtime, validates an actual request, deploys successfully, and returns the same response after deployment. Once that path is stable, add the database, storage, AI, or queue integration your application actually needs.
Python Workers reaching general availability changes the question for Python developers from whether Python can run on Cloudflare to which parts of an existing Python application belong there. For a new API, starting with FastAPI and pywrangler gives you a short path from Python code to a globally deployed Worker. For an existing service, the dependency and runtime compatibility checks should come first, because those will determine how much of the application can move without redesign.
Written by


