Skip to content

Flask

Last updated View as MarkdownAgent setup

Flask is supported in Python Workers.

Flask applications rely on a protocol called the Web Server Gateway Interface (WSGI). This means that Flask never directly reads or writes to a socket, instead relying on the WSGI server to communicate.

Python Workers include a WSGI server which you can use with Flask applications.

Prerequisites

You need uv and node installed.

Create a Flask Worker

Use this quick start to run a minimal Flask application.

  1. Create src/worker.py with your flask application:

    src/worker.pypython
    from flask import Flask
    from workers import wsgi
    
    app = Flask(__name__)
    
    @app.get("/")
    def index():
        return {"message": "Hello from Flask"}
    
    Default = wsgi.entrypoint(app)
  2. In the project root, create wrangler.jsonc:

    {
      "$schema": "node_modules/wrangler/config-schema.json",
      "name": "my-flask-worker",
      "main": "src/worker.py",
      // Set this to today's date
      "compatibility_date": "2026-08-28",
      "compatibility_flags": ["python_workers"]
    }
    "$schema" = "node_modules/wrangler/config-schema.json"
    name = "my-flask-worker"
    main = "src/worker.py"
    # Set this to today's date
    compatibility_date = "2026-08-28"
    compatibility_flags = [ "python_workers" ]
  3. Create a pyproject.toml to declare dependencies:

    pyproject.tomltoml
    [project]
    name = "flask-worker"
    version = "0.1.0"
    requires-python = ">=3.12"
    dependencies = [
        "flask",
    ]
    
    [dependency-groups]
    dev = [
        "workers-py",
        "workers-runtime-sdk",
    ]
  4. Start the local development server:

    uv run pywrangler dev
  5. In another terminal, send a request to the Worker:

    curl http://localhost:8787/

    The Worker returns:

    {"message":"Hello from Flask"}

Serve a frontend

You can serve any static frontend alongside your flask backend by using Workers Static Assets. Using Static Assets means your frontend files are not bundled inside the Worker itself, keeping the bundle small.

Place your static 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.

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-flask-worker",
  "main": "src/worker.py",
  // Set this to today's date
  "compatibility_date": "2026-08-28",
  "compatibility_flags": ["python_workers"],
  "assets": {
    "directory": "./public/",
    "binding": "ASSETS",
    "run_worker_first": true
  }
}
"$schema" = "node_modules/wrangler/config-schema.json"
name = "my-flask-worker"
main = "src/worker.py"
# Set this to today's date
compatibility_date = "2026-08-28"
compatibility_flags = [ "python_workers" ]

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

The following Worker handles an API route before forwarding other requests. The catch-all handlers return each asset's body, status, and headers:

src/worker.pypython
from flask import Flask, Response, request
from pyodide.ffi import run_sync
from workers import wsgi


app = Flask(__name__)


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


@app.get("/")
@app.get("/<path:path>")
def frontend(path=""):
    assets = request.environ["workers.env"].ASSETS
    asset_response = run_sync(assets.fetch(f"https://assets.local/{path}"))
    body = run_sync(asset_response.bytes())
    return Response(
        body,
        status=asset_response.status,
        headers=asset_response.headers,
    )


Default = wsgi.entrypoint(app)

run_sync bridges both asynchronous asset operations into Flask's synchronous handler. API routes take priority, and unmatched paths are served from ./public/.

More examples

Run the Flask todo example from the python-workers-examples repository.

  1. Clone the examples repository:

    git clone https://github.com/cloudflare/python-workers-examples
  2. Enter the Flask todo example directory:

    cd python-workers-examples/flask-todo
  3. Initialize the local D1 database from db_init.sql:

    uv run pywrangler d1 execute todos --local --file db_init.sql
  4. Start the local development server:

    uv run pywrangler dev

Was this helpful?