# How to Deploy a FastAPI App for Free (2026, with PostgreSQL)

Deploy FastAPI with Uvicorn workers bound to PORT, async PostgreSQL via SQLAlchemy and settings from the environment, starting on a free plan with HTTPS.

URL: https://blog.dockhosting.dev/deploy-fastapi-app
Published: 2026-10-30 · Updated: 2026-10-30 · Author: Doughmi ILYAS

## Summary

- In production, run FastAPI with Uvicorn workers bound to 0.0.0.0 and the PORT environment variable.
- Load configuration from environment variables with pydantic-settings, and the database from DATABASE_URL.
- DockHosting detects FastAPI from requirements.txt or pyproject.toml, runs it with async workers and gives you HTTPS.

ort const meta = {
  title: "How to Deploy a FastAPI App for Free (2026, with PostgreSQL)",
  seoTitle: "Deploy a FastAPI App for Free (2026, with PostgreSQL)",
  description:
    "Deploy FastAPI with Uvicorn workers bound to PORT, async PostgreSQL via SQLAlchemy and settings from the environment, starting on a free plan with HTTPS.",
  date: "2026-10-30",
  category: "Guides",
  tags: ["FastAPI", "Python", "API", "Deployment", "Tutorial"],
  stack: ["fastapi", "pydantic", "postgresql"],
  command: "dock deploy",
  takeaways: [
    "In production, run FastAPI with Uvicorn workers bound to 0.0.0.0 and the PORT environment variable.",
    "Load configuration from environment variables with pydantic-settings, and the database from DATABASE_URL.",
    "DockHosting detects FastAPI from requirements.txt or pyproject.toml, runs it with async workers and gives you HTTPS.",
  ],
  faq: [
    {
      q: "Should I use Uvicorn or Gunicorn for FastAPI in production?",
      a: "Both work. Uvicorn alone with --workers is simple and fine for most apps. Gunicorn with Uvicorn workers adds process management. On DockHosting the start command is set for you and you can override it.",
    },
    {
      q: "Why is my FastAPI docs page (/docs) blank in production?",
      a: "Usually a proxy or root_path issue. If you serve the app under a sub-path, set root_path. When the app is served at the root of its own domain, /docs works without changes.",
    },
    {
      q: "Which Python versions are supported?",
      a: "Python 3.11 and 3.12, with pip (requirements.txt) or Poetry (pyproject.toml).",
    },
  ],
};

FastAPI makes building an API fast. Deploying it means choosing a server process, binding the right address, managing settings and connecting a database. This guide takes a FastAPI app to a production HTTPS URL.

## 1. A minimal production-ready app

```python
# main.py
from fastapi import FastAPI

app = FastAPI(title="My API")

@app.get("/health")
async def health():
    return {"status": "ok"}

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}
```

```text
# requirements.txt
fastapi
uvicorn[standard]
pydantic-settings
sqlalchemy
psycopg[binary]
```

A `/health` endpoint costs nothing and makes debugging deploys much easier.

## 2. The start command

In production, Uvicorn has to listen on **all interfaces** and on the **port the platform assigns**:

```bash
uvicorn main:app --host 0.0.0.0 --port $PORT --workers 2
```

Or with Gunicorn managing Uvicorn workers:

```bash
gunicorn main:app -k uvicorn.workers.UvicornWorker -w 2 -b 0.0.0.0:$PORT
```

On DockHosting, FastAPI is detected from `fastapi` in your requirements and runs under Uvicorn/Gunicorn with async workers. You can override the start command in the project settings, and start commands with `$` variables like `$PORT` work.

> Don't use `--reload` in production. It watches files, uses more memory and restarts your server on changes.

## 3. Settings from the environment

[pydantic-settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/) reads and validates configuration, and fails at startup with a clear message when something is missing:

```python
# settings.py
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    database_url: str
    api_key: str
    debug: bool = False

settings = Settings()  # reads DATABASE_URL, API_KEY, DEBUG
```

If a variable is missing, the crash message names the invalid field, and DockHosting shows that message in the deploy's App output tab.

## 4. PostgreSQL with async SQLAlchemy

Attach a managed PostgreSQL database in the dashboard, and `DATABASE_URL` is injected over the private network.

```python
# db.py
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from settings import settings

url = settings.database_url.replace("postgresql://", "postgresql+psycopg://", 1)
engine = create_async_engine(url, pool_pre_ping=True)
Session = async_sessionmaker(engine, expire_on_commit=False)
```

`pool_pre_ping` replaces dropped connections quietly, which is useful when Free-plan apps wake up from sleep. Run Alembic migrations as part of your start command, for example `alembic upgrade head && uvicorn …`.

## 5. Deploy

```bash
curl -fsSL https://cli.dockhosting.dev/install.sh | sh   # Windows: irm https://cli.dockhosting.dev/install.ps1 | iex
dock login
dock deploy
```

You get `https://<project>.dockhosting.cloud` with automatic HTTPS, and your interactive docs at `/docs`. Add `API_KEY` and any other settings as environment variables, then run `dock restart`.

## 6. CORS for a frontend

If a React or Vue app on another domain calls your API, allow its origin explicitly:

```python
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://myapp.dockhosting.cloud"],
    allow_methods=["*"],
    allow_headers=["*"],
)
```

Avoid `allow_origins=["*"]` together with credentials. Browsers reject it, and it's unsafe.

## Plans

The Free plan runs a FastAPI app with a PostgreSQL database at $0. It sleeps after 1 hour without requests and wakes on the next one. For an API that real users depend on, Hobby ($4/month) is always on and adds your own domain. See [pricing](https://dockhosting.dev/pricing).

Getting a 502? Check the [8 most common causes](/fix-502-bad-gateway-after-deploy). Building with Django instead? See the [Django deploy guide](/deploy-django-app-production).

## FAQ

### Should I use Uvicorn or Gunicorn for FastAPI in production?

Both work. Uvicorn alone with --workers is simple and fine for most apps. Gunicorn with Uvicorn workers adds process management. On DockHosting the start command is set for you and you can override it.

### Why is my FastAPI docs page (/docs) blank in production?

Usually a proxy or root_path issue. If you serve the app under a sub-path, set root_path. When the app is served at the root of its own domain, /docs works without changes.

### Which Python versions are supported?

Python 3.11 and 3.12, with pip (requirements.txt) or Poetry (pyproject.toml).
