Deploy a FastAPI app

Deploy a FastAPI app on Hangar with uvicorn, a managed PostgreSQL database, Alembic migrations on release and HTTPS on your domain.

Updated

FastAPI runs on Hangar as a long-lived uvicorn server in a container. WebSockets, streaming responses and background tasks work as they do on your machine.

Before you start

  • A FastAPI app in a Git repository, with its dependencies in requirements.txt or pyproject.toml:
fastapi
uvicorn[standard]

1. Create the service

Create a project, add a service and pick your repository and branch. Choose the region closest to your users, and leave the builder on Automatic: it detects Python and installs your dependencies, with pip, uv or Poetry depending on the files in the repository.

2. Set the start command

In the service's Settings → Runtime, set the start command:

uvicorn main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips=*
  • main:app is the module and the variable that holds your FastAPI() instance. Adjust it to your layout, for example app.main:app.
  • --host 0.0.0.0 is required. On 127.0.0.1 the proxy cannot reach the app.
  • --proxy-headers makes the app see the original scheme and client address, since Hangar terminates TLS in front of it.

To use more than one CPU core, add --workers 2 and raise the number with the service's CPU limit.

3. Deploy and add a domain

Deploy the service. In Settings → Networking, add a domain with container port 8000 and HTTPS on. Your interactive API docs are then at /docs on that domain.

Adding PostgreSQL

Add a PostgreSQL service in the same project and region, copy its internal connection URL and set it on the app:

DATABASE_URL=<the internal connection URL>

Read it in your code:

import os
from sqlalchemy import create_engine

engine = create_engine(os.environ["DATABASE_URL"], pool_pre_ping=True)

With an async driver, replace the scheme of the URL, for example postgresql+asyncpg://.

Migrations

Run Alembic before the server, so each release migrates first. Chained commands need a shell: set the start command to sh and add two arguments, -c and this line:

alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips="*"

Inside the shell the quotes around * matter; in the plain start command above they must be left out. See Start command.

Background workers

Celery, ARQ or RQ workers run as a second service from the same repository, with their own start command and a Redis database as the broker. See Databases.

Troubleshooting

  • 502 on the domain: uvicorn is bound to 127.0.0.1, or the container port is not 8000.
  • Redirects go to http://: --proxy-headers is missing.
  • ModuleNotFoundError at start: the module path in the start command does not match the repository layout, or the service's root directory is wrong.

Frequently asked questions

What start command does FastAPI need on Hangar?
Start uvicorn on all interfaces and a fixed port, for example uvicorn main:app --host 0.0.0.0 --port 8000, and use the same port as the domain's container port.
Do WebSockets and background tasks work with FastAPI on Hangar?
Yes. Your app runs as a long-lived server in a container, not as a function per request, so WebSockets, streaming responses and background tasks behave as they do locally.
How do I run Alembic migrations on deploy?
Chain the migration before the server in the start command, through a shell, setting the command to sh with the arguments -c and alembic upgrade head && uvicorn main:app --host 0.0.0.0 --port 8000.

Deploy your app on Hangar

Connect a repository and it is live in minutes.

Start deploying