Skip to content

FastAPI

Last updated View as MarkdownAgent setup

The FastAPI package is supported in Python Workers.

FastAPI applications use a protocol called the Asynchronous Server Gateway Interface (ASGI). This means that FastAPI never reads from or writes to a socket itself. An ASGI application expects to be hooked up to an ASGI server, typically uvicorn. The ASGI server handles all of the raw sockets on the application’s behalf.

The Python Workers provide an ASGI server that you can use directly in your Python Worker, which lets you use FastAPI in Python Workers.

Quick Start

To get started with FastAPI in Python Workers, follow these steps:

  1. Create a src/main.py file with your FastAPI application:
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

import asgi
from workers import WorkerEntrypoint

class Default(WorkerEntrypoint):
    async def fetch(self, request):
        return await asgi.fetch(app, request, self.env)
  1. Create a wrangler.jsonc file to configure your Worker:
{
	"name": "my-fastapi-app",
	"main": "src/main.py",
	// Set this to today's date
	"compatibility_date": "2026-08-22",
	"compatibility_flags": ["python_workers"],
}
name = "my-fastapi-app"
main = "src/main.py"
# Set this to today's date
compatibility_date = "2026-08-22"
compatibility_flags = [ "python_workers" ]
  1. Create a pyproject.toml file to manage your dependencies:
[project]
name = "my-fastapi-app"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
    "fastapi",
]

[dependency-groups]
dev = [
    "workers-py",
    "workers-runtime-sdk"
]
  1. Run your Worker locally:
uv run pywrangler dev

Serve a frontend

You can serve a single-page application (SPA) or any static frontend alongside your FastAPI backend by using Workers Static Assets.

This is equivalent to FastAPI's native app.frontend() method, which serves a static build directory as low-priority routes so that API path operations are checked first. The difference is where the files live: app.frontend() reads files from the local filesystem, while on Workers the static assets are served from Cloudflare's globally distributed asset store through the ASSETS binding. This means your frontend files are not bundled inside the Worker itself, keeping the bundle small.

Place your frontend build output (for example, HTML, CSS, and JavaScript files) in a directory such as ./public/. Then configure your Wrangler file with an assets block that includes a binding and sets run_worker_first to true. This ensures every request reaches your FastAPI Worker first, so your API routes take priority over static files.

Add a catch-all route at the end of your FastAPI app that proxies unmatched requests to the assets binding:

{
	"name": "my-fastapi-app",
	"main": "src/worker.py",
	// Set this to today's date
	"compatibility_date": "2026-08-22",
	"compatibility_flags": ["python_workers"],
	"assets": {
		"directory": "./public/",
		"binding": "ASSETS",
		"run_worker_first": true
	}
}
name = "my-fastapi-app"
main = "src/worker.py"
# Set this to today's date
compatibility_date = "2026-08-22"
compatibility_flags = [ "python_workers" ]

[assets]
directory = "./public/"
binding = "ASSETS"
run_worker_first = true

Be sure to create a pyproject.toml file to manage your dependencies:

[project]
name = "my-fastapi-app"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
    "fastapi",
]

[dependency-groups]
dev = [
    "workers-py",
    "workers-runtime-sdk"
]

Then write your worker:

src/worker.pypython
from workers import WorkerEntrypoint
from fastapi import FastAPI, Request
from fastapi.responses import Response
import asgi

class Default(WorkerEntrypoint):
    async def fetch(self, request):
        return await asgi.fetch(app, request, self.env)

app = FastAPI()

@app.get("/api/hello")
async def api_hello():
    return {"message": "Hello from the API"}

# Catch-all: proxy everything else to Workers Static Assets.
# This is the Workers equivalent of app.frontend("/", directory="dist").
@app.get("/{path:path}")
async def frontend(path: str, request: Request):
    env = request.scope["env"]
    asset_url = f"https://assets.local/{path}"
    resp = await env.ASSETS.fetch(asset_url)
    body = await resp.bytes()
    headers = dict(resp.headers)
    return Response(content=body, status_code=resp.status, headers=headers)

You can run this worker locally using uv run pywrangler dev.

With this setup, a request to /api/hello is handled by FastAPI, while a request to /index.html or any other path is served from the ./public/ directory through the assets binding.

For more information on configuring static assets, refer to the Workers Static Assets documentation.

More examples

Clone the cloudflare/python-workers-examples repository and run the FastAPI examples there:

git clone https://github.com/cloudflare/python-workers-examples
cd python-workers-examples/03-fastapi
uv run pywrangler dev

Was this helpful?