Skip to content

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.

Published
Reading time
3 min
On this page

Key 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.

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.

3. Settings from the environment

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.

Getting a 502? Check the 8 most common causes. Building with Django instead? See the Django deploy guide.

Frequently asked questions

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).

  • FastAPI
  • Python
  • API
  • Deployment
  • Tutorial

Written by Doughmi ILYAS

Doughmi builds DockHosting, the developer-first platform behind dock deploy: the build system, the managed databases and the dashboard. On this blog: guides to shipping apps without running servers, written with the commands the platform actually ships.

Summarize with

Share

All posts

Create an account, run dock deploy, and get a live HTTPS URL in minutes.