Skip to content

Deployment

Terminal window
pymode deploy

This bundles your Python code, stdlib, and dependencies into a Cloudflare Worker with a PythonDO Durable Object.

ComponentSizeDescription
python.wasm5.7MB (1.8MB gz)CPython 3.13 runtime
stdlib bundle~150KBEssential stdlib modules
Your codevariesPython source files
DependenciesvariesInstalled packages
Worker JS~20KBWorker entry + WASI + Asyncify runtime

Total bundle size is typically 2-3MB gzipped, well within Cloudflare’s 10MB limit.

Wizer pre-initializes the Python runtime at deploy time, reducing cold start from ~28ms to ~5ms. The build script exists (scripts/build-wizer.py) but this feature requires additional testing.

Terminal window
pymode deploy --wizer
  1. At deploy time, Wizer runs python.wasm up to the point where CPython is fully initialized
  2. It takes a memory snapshot at that point
  3. At runtime, the snapshot is loaded directly — skipping all initialization

This is particularly effective because CPython’s startup (loading frozen modules, initializing builtins, importing site) is the dominant cold-start cost.

Create a .dev.vars file in your project root:

Terminal window
API_KEY=sk-test-123
DATABASE_URL=postgres://localhost:5432/mydb

Use Wrangler to set secrets:

Terminal window
# Set a secret
wrangler secret put API_KEY
# List secrets
wrangler secret list
# Delete a secret
wrangler secret delete API_KEY

Access in Python:

def on_fetch(request, env):
api_key = env.API_KEY

Configure in wrangler.toml:

routes = [
{ pattern = "api.example.com/*", zone_name = "example.com" }
]

Or use Cloudflare’s dashboard to add a custom domain to your Worker.

View real-time logs:

Terminal window
wrangler tail

Cloudflare Workers analytics are available in the dashboard:

  • Request count
  • CPU time per request
  • Error rate
  • Cold start frequency

Python tracebacks are captured in Worker logs. Use wrangler tail or the Cloudflare dashboard to view them.

def on_fetch(request, env):
try:
return handle(request, env)
except Exception as e:
# Logged automatically to Worker logs
print(f"Error: {e}", file=sys.stderr)
return Response("Internal Server Error", status=500)
ResourceLimit
Worker size10MB (compressed)
CPU time per request30s
Memory per DO128MB
Subrequests per request50
KV value size25MB
R2 object size5GB
D1 database size10GB
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
run: npm install
- name: Deploy
run: npx wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
SecretDescription
CF_API_TOKENCloudflare API token with Workers write permission