Short answer: Cloudflare’s September 21 Python Workers GA announcement makes Python a fully supported Workers language. The current experience includes Pythonic bindings, ASGI/WSGI framework bridges, and broader WebAssembly package support. It can suit an HTTP API, webhook, or AI orchestration endpoint when its dependencies, state model, and CPU and memory use fit the Workers runtime. It is not a Linux container: Python runs through Pyodide/WebAssembly in a V8 isolate, and native packages still need a compatible Wasm build.
Use this guide to decide whether an existing Python service can move, run a source-based FastAPI starter, and test the constraints that matter before you shift production traffic. Cloudflare’s examples and the code below are documentation examples; DMT did not execute a deployment or benchmark.
What changed at GA—and what did not
Cloudflare describes GA as Python becoming a first-class, fully supported language on its Developer Platform. Python Workers can use platform bindings such as Workers AI, R2, D1, Hyperdrive, Durable Objects, Queues, and Workflows. The runtime now handles common Python-to-JavaScript value conversion at binding boundaries, so a Python dictionary can be sent to a Queue without manually converting it to a JavaScript object. FastAPI connects through the supplied ASGI adapter; Django and Flask can use the WSGI adapter. The Worker runtime provides the request handling, so you do not launch Uvicorn or Gunicorn as a separate process inside it.
The execution model is still important: Workers run CPython compiled to WebAssembly through Pyodide, inside a V8 isolate. Cloudflare runs module-level imports and initialization at deployment and snapshots the Wasm memory to reduce initialization work when an isolate starts. That does not establish a universal cold-start time or Python-versus-JavaScript performance result. Treat GA as a support and integration milestone, then measure your own dependency set and workload.
Use this compatibility matrix before you migrate
Start with the code and infrastructure assumptions your app actually needs. The Cloudflare docs linked in the table are the authority for current version-specific support.
| What your app needs | Documented Python Workers behavior | Migration decision |
|---|---|---|
| Framework server | FastAPI uses workers.asgi; Django and Flask can use workers.wsgi. The Worker runtime handles incoming requests. | Keep the framework application where possible; replace the process/server entrypoint with the Worker adapter. Do not try to launch a long-running web-server process. |
| Python packages | Pywrangler supports pure-Python packages, PyEmscripten wheels from PyPI, and packages shipped with Pyodide. Some native-extension packages still lack a compatible wheel. | Audit direct and transitive dependencies for Wasm wheels, then install and build through Pywrangler. A package that installs on Linux is not proof it will install for Pyodide. |
| PostgreSQL or MySQL | Hyperdrive uses the Workers TCP socket API. The current guide lists asyncpg, pg8000, or psycopg for PostgreSQL and aiomysql or pymysql for MySQL. Async SQLAlchemy is not supported in the current Python Workers environment. | Use a Hyperdrive binding and check driver/ORM support. Hyperdrive requires a compatibility date of 2026-09-08 or later; synchronous SQLAlchemy is documented, async SQLAlchemy is not. |
| Background work or parallel threads | Python’s threading and multiprocessing modules are present but nonfunctional under this WebAssembly runtime. | Move durable jobs to a platform service such as Queues or Workflows; redesign process-based workers rather than assuming they will run unchanged. |
| Local files and persistent state | File I/O uses an in-memory filesystem that disappears when an isolate is destroyed and is not shared between isolates. | Store durable data in R2, D1, KV, Durable Objects, or an external database; use local files only for temporary work. |
This is a fit check, not a claim that the listed frameworks or drivers are interchangeable with every app configuration. For example, Cloudflare’s Hyperdrive Python guide names the tested drivers and notes that some low-level socket operations may behave differently. Confirm the exact versions and access pattern your app uses.
Check the Workers limits against your workload
The following are general Workers plan/runtime limits, not Python-specific performance measurements. WebAssembly memory counts toward the per-isolate ceiling, so the Python interpreter and packages share that budget with the rest of the Worker.
| Limit | Workers Free | Workers Paid | Why a Python team should check it |
|---|---|---|---|
| HTTP CPU time | 10 ms per request | 30-second default; configurable up to 5 minutes | CPU work counts, while waiting on network I/O does not. Separate Python computation from database/API wait time in your test. |
| Memory per isolate | 128 MB | 128 MB | Includes JavaScript heap and WebAssembly allocations, including Python/Pyodide memory. |
| Uncompressed Worker bundle | 64 MiB | 64 MiB | Packages are bundled at deploy time; check the uncompressed bundle, not its gzip size. |
| Startup | 1 second | 1 second | Global-scope code must parse and execute within the startup budget. Expensive imports or module-level initialization can cause deploy validation to fail. |
| Requests | 100,000 per day | No request limit | Check the plan separately from CPU, memory, and database quotas. |
Cloudflare documents the complete Workers limits page, including request-body and subrequest limits. For Python, pay special attention to the 128 MB memory ceiling, package bundle size, and CPU allowance. Deployment snapshots can move some initialization work earlier, but they do not remove these budgets or prove latency for your app.
Do not treat the free 10 ms CPU allowance as a first-request wall-time target. Cloudflare defines CPU time as code execution and excludes network wait. Its Python deployment flow also executes module-level imports at deploy time and snapshots the Wasm memory. Those facts still do not establish a cold-start number for your app: measure first-request and warm-request latency separately from CPU time.
Start with a source-based FastAPI Worker
Cloudflare’s Python setup requires uv and Node.js. The Python Workers guide recommends initializing with Pywrangler, which creates the project and Wrangler configuration. The package guide shows this dependency shape for a FastAPI starter:
[project]
name = "edge-api"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = ["fastapi"]
[dependency-groups]
dev = ["workers-py", "workers-runtime-sdk"]
Initialize the project and confirm the generated Wrangler config points to your Python entry file, sets a current compatibility date, and includes the python_workers compatibility flag:
uvx --from workers-py pywrangler init
Review the generated wrangler.jsonc configuration. A minimal JSON-compatible shape is:
{
"name": "edge-api",
"main": "src/main.py",
"compatibility_date": "2026-09-23",
"compatibility_flags": ["python_workers"]
}
For a Hyperdrive-backed database connection, set the compatibility date to September 8, 2026 or later and add the binding required by your Hyperdrive configuration. Always check Cloudflare’s compatibility documentation before updating an existing Worker’s date; dates opt into runtime behavior changes and should be tested.
Save the following as src/main.py to match the example Wrangler config above; if your initialized project uses another filename, point its main setting to that file. This follows Cloudflare’s documented ASGI adapter pattern:
from fastapi import FastAPI
from workers import asgi
app = FastAPI()
@app.get("/health")
def health():
return {"status": "ok"}
Default = asgi.entrypoint(app)
With the route loaded, a successful GET /health should return JSON containing {"status":"ok"}. That is the expected result from the example, not an observed DMT test. Run the local Worker, then deploy it with the documented commands:
uv run pywrangler dev
uv run pywrangler deploy
The source example does not prove that your application’s dependency tree, authentication, database connection, or workload fits. DMT did not run these commands. Check the local startup result and deployment bundle, then test the deployed route using production-shaped requests before routing traffic.
A practical migration checklist
- Inventory the dependency tree. Include transitive packages. For native extensions, confirm that the exact package version has a PyEmscripten wheel or is included with Pyodide. A standard Linux wheel is not enough.
- Replace server startup, not necessarily your routes. FastAPI/ASGI uses
workers.asgi; Django and Flask/WSGI useworkers.wsgi. Remove reliance on a daemon, long-lived process, or separate Uvicorn/Gunicorn listener inside the Worker. - Move state and long-running work to platform services. Treat the Python filesystem as temporary and per-isolate. Use a binding or database for durable state; use Queues or Workflows for asynchronous work that should continue beyond a request.
- Verify network and database paths. For Hyperdrive, configure the binding, use a documented driver, and check the compatibility-date requirement. If the service depends on async SQLAlchemy, greenlets, or raw socket behavior, test the exact path or keep that component on its current runtime.
- Measure the production-shaped route. Record response correctness, error rate, CPU time, memory, package bundle size, and latency under expected concurrency. Separate network wait from CPU time. Test free and paid limits against the plan you intend to use.
- Move traffic gradually. Begin with a low-risk route or staging environment, compare it with the current service, and keep a rollback path until logs and failure cases are understood.
When Python Workers are a good fit
Good fit: an HTTP-facing API, webhook, edge authorization step, request transformation, database-backed endpoint, or AI orchestration route that can use Workers bindings, has dependencies available for Pyodide, and stays within the memory and CPU budgets. This is an architecture recommendation inferred from Cloudflare’s documented runtime and limits, not a measured speed or cost comparison.
If the Worker will call a model with a tool loop, our GPT-6 Astra API coding guide covers a source-checked Responses API pattern. That page handles the model-call layer; this guide covers the Cloudflare runtime.
Keep a container or another Python host in the comparison: if the app needs a broad Linux package ecosystem, unsupported native wheels, functioning threads or multiprocessing, persistent local files, OS-level services, or substantial CPU-bound work. GA improves the production support and platform integration story; it does not make those runtime differences disappear.
Sources and testing note
Primary references: Cloudflare’s September 21 GA announcement, Python Workers setup, supported packages, runtime and deployment lifecycle, standard library, Hyperdrive drivers and setup, compatibility dates, and Workers limits. Code follows Cloudflare documentation and is an unexecuted starter, not a DMT deployment or compatibility test.