Build a FastAPI app

Run a typed Python API on Falix — validation and an interactive docs page come free from your type hints, with uvicorn serving it on SERVER_PORT.

FastAPI gives you a typed Python API with automatic request validation and a live, interactive docs page — for very little code. It runs on the Python application with one Falix rule to respect: you start the server yourself, bound to SERVER_PORT. Here's the whole setup.

At a glance
You need A server running the Python application
Plan Any plan
Time Fifteen minutes

For how Python starts here — the app.py entry file and requirements.txt that installs on start — see Python on Falix.

Two files

FastAPI needs an ASGI server to actually run it; uvicorn is the standard one. List both in requirements.txt:

fastapi
uvicorn

The Python application installs everything in requirements.txt on start, so that's the entire dependency setup. (Prefer the panel? Search fastapi and uvicorn on the Packages page and it writes the same file for you.)

Then app.py:

import os

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"message": "Hello from FastAPI on Falix!"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}


if __name__ == "__main__":
    import uvicorn

    port = int(os.environ.get("SERVER_PORT", 8080))
    print(f"Listening on port {port}", flush=True)
    uvicorn.run(app, host="0.0.0.0", port=port)

Press Start. The console installs FastAPI and uvicorn, prints Listening on port …, and your API is live at your server's address (from the Network page).

What the routes show

  • Return a dict and FastAPI sends JSON. read_root gives {"message": ...} with no extra work.
  • {item_id} in the path is a path parameter. Typing it item_id: int means FastAPI validates and converts it — /items/3 works, and /items/abc gets an automatic 422 error with no code from you.
  • q: str | None = None is a query parameter. /items/3 returns q as null; /items/3?q=hello returns "hello".

🎯 Good to know: The types aren't decoration — they are the validation. That's the whole FastAPI idea in one line.

The docs page you get for free

Because your routes are typed, FastAPI generates interactive API documentation automatically. Open /docs on your server's address and you get a live page listing every route, its parameters, and a Try it out button that calls your API for real. You wrote no docs; they came straight from the type hints. (There's a second style at /redoc.)

Async when you need it

FastAPI handlers can be async def when a route does I/O that can overlap — an outbound HTTP request, an async database driver. Write plain def for ordinary work and async def when you have something to await; both are first-class.

💡 Tip: Reach for async only where it buys you something.

One process is plenty here

Plenty of FastAPI guides reach for multiple uvicorn workers, or gunicorn, "for production." On a Falix app server you don't need to: a single uvicorn.run(app, ...) process is the right fit. You have one public port and shared RAM, and because FastAPI is async, one process serves many overlapping requests happily. Extra worker processes mostly pay off on big multi-core machines under heavy traffic — beyond what a single app server here is for — and each one costs more memory. Keep the one process; reach for more only if you genuinely outgrow it, on a plan with the resources to match.

Extra packages

For anything beyond FastAPI itself — an async database driver, an HTTP client, python-multipart for form uploads — use the Packages page in your server menu: search the name, install, restart. Your requirements.txt is updated for you.

Flask or FastAPI?

Flask is the minimal, synchronous classic (Build a Flask web app); FastAPI layers typed validation and the automatic /docs on top. If you want request validation and API docs handed to you, pick FastAPI; for a tiny site or template-rendered pages, Flask stays lighter.

Troubleshooting

  • ModuleNotFoundError: No module named 'fastapi' (or 'uvicorn') — not installed. Add both on the Packages page and restart.
  • Page won't load / connection refused — uvicorn must bind host="0.0.0.0" with the port read from SERVER_PORT. See I can't reach my app.
  • Address already in use / error while attempting to bind — you're starting uvicorn twice, or hardcoded a port that isn't SERVER_PORT. Keep exactly one uvicorn.run reading SERVER_PORT.
  • Server starts and exits with no API — you defined app but never call uvicorn.run (or the if __name__ block is indented wrong). That call is what keeps the process alive.

Next steps

Was this guide helpful?