Python Workers Went GA: CPython in a V8 Isolate
Cloudflare just made Python Workers generally available. Real CPython at the edge, FastAPI in one command — and the catches to know first.
Cloudflare just moved Python Workers out of beta and into general availability. You can now deploy plain CPython to the same edge network that runs your JavaScript Workers — no container, no uvicorn, no picking a region.
Python has been the awkward guest at the edge party for a decade. If your team wrote Python, your options were a VM in one region or a rewrite in TypeScript. As of today, the rewrite is optional.
Why this matters
"Serverless Python" has usually meant a container cold-booting in a single region. Workers are a different shape: your code runs in isolates across 300+ Cloudflare locations, on the same pay-per-request model as every other Worker. That puts Python where it previously couldn't afford to live — in front of users, next to KV, R2, and Queues, deployed with the same wrangler pipeline your frontend team already uses. A lot of internal glue services just stopped needing their own infrastructure.
How it works
The runtime is Pyodide: real CPython compiled to WebAssembly, embedded in workerd — the same V8-isolate runtime JavaScript Workers use. Your entry point is a single on_fetch function, and bindings like KV or R2 arrive through the js module, which proxies JavaScript objects into Python.
Package handling is the clever part. You don't list dependencies anywhere — you write from fastapi import FastAPI, and the build step scans your imports, resolving each against a snapshot of prebuilt Pyodide wheels kept on the edge.
Cold starts were the historical killer for WASM Python: initializing Pyodide takes seconds. The fix is snapshotting. At deploy time, workerd captures the fully initialized interpreter plus your packages, and each new isolate restores from that snapshot instead of booting Python from scratch.
Where this helps
- FastAPI microservices. ASGI apps deploy with one command. No uvicorn, no gunicorn tuning, no Dockerfile.
- Cron work. Scheduled backfills, cache warms, and report jobs run on Cron Triggers instead of a container on a scheduler somewhere.
- Data munging near users. Normalize payloads, reshape CSVs, and run numpy-backed math before traffic hits your origin.
- Mixed stacks. Python handles the logic; existing JS Workers, bindings, and routes stay exactly where they are.
Watch out
- No sockets, no subprocesses. Only packages in the Pyodide snapshot are installable. The long tail of pip is off-limits, and version pinning is limited to what the snapshot contains.
- CPU limits still apply. The GIL is alive, and Workers will terminate long-running computation. Heavy number crunching belongs elsewhere.
- The JS boundary costs. Proxying thousands of tiny objects between Python and JS per request will hurt. Batch your crossings.
- Snapshots grow with imports. Pull in pandas "just in case" and every isolate restore pays for it. Import what you use.
Try it yourself
Five lines of Python, deployed to the edge:
mkdir hello-edge && cd hello-edge
npm init -y >/dev/null && npm i -D wrangler >/dev/null
cat > worker.py <<'PY'
from js import Response
async def on_fetch(request, env, ctx):
return Response.new("CPython, at the edge")
PY
cat > wrangler.jsonc <<'JSON'
{ "name": "hello-edge", "main": "worker.py", "compatibility_date": "2026-09-22" }
JSON
npx wrangler dev # then: curl localhost:8787TL;DR
- What changed: Cloudflare's Python Workers are generally available — real CPython, deployed like any other Worker.
- Why it matters: Python without containers, cold-booting regions, or a TypeScript rewrite, sitting next to your existing bindings.
- Try today: the worker above, then swap in FastAPI and watch import detection do the rest.