Deployment
Standard Deployment
Section titled “Standard Deployment”pymode deployThis bundles your Python code, stdlib, and dependencies into a Cloudflare Worker with a PythonDO Durable Object.
What Gets Deployed
Section titled “What Gets Deployed”| Component | Size | Description |
|---|---|---|
python.wasm | 5.7MB (1.8MB gz) | CPython 3.13 runtime |
| stdlib bundle | ~150KB | Essential stdlib modules |
| Your code | varies | Python source files |
| Dependencies | varies | Installed packages |
| Worker JS | ~20KB | Worker entry + WASI + Asyncify runtime |
Total bundle size is typically 2-3MB gzipped, well within Cloudflare’s 10MB limit.
Wizer Snapshots (Experimental)
Section titled “Wizer Snapshots (Experimental)”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.
pymode deploy --wizerHow It Works
Section titled “How It Works”- At deploy time, Wizer runs
python.wasmup to the point where CPython is fully initialized - It takes a memory snapshot at that point
- 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.
Environment Variables and Secrets
Section titled “Environment Variables and Secrets”Development
Section titled “Development”Create a .dev.vars file in your project root:
API_KEY=sk-test-123DATABASE_URL=postgres://localhost:5432/mydbProduction
Section titled “Production”Use Wrangler to set secrets:
# Set a secretwrangler secret put API_KEY
# List secretswrangler secret list
# Delete a secretwrangler secret delete API_KEYAccess in Python:
def on_fetch(request, env): api_key = env.API_KEYCustom Domains
Section titled “Custom Domains”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.
Monitoring
Section titled “Monitoring”View real-time logs:
wrangler tailMetrics
Section titled “Metrics”Cloudflare Workers analytics are available in the dashboard:
- Request count
- CPU time per request
- Error rate
- Cold start frequency
Error Tracking
Section titled “Error Tracking”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)Limits
Section titled “Limits”| Resource | Limit |
|---|---|
| Worker size | 10MB (compressed) |
| CPU time per request | 30s |
| Memory per DO | 128MB |
| Subrequests per request | 50 |
| KV value size | 25MB |
| R2 object size | 5GB |
| D1 database size | 10GB |
GitHub Actions
Section titled “GitHub Actions”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 }}Required Secrets
Section titled “Required Secrets”| Secret | Description |
|---|---|
CF_API_TOKEN | Cloudflare API token with Workers write permission |