# FastAPI Production Deployment on DomainIndia VPS (Gunicorn + Uvicorn + nginx + PostgreSQL)
TL;DR
FastAPI is the dominant Python API framework of 2026 — async-first, type-safe, auto-OpenAPI docs. This guide deploys a production FastAPI app on DomainIndia VPS: Uvicorn workers under Gunicorn, systemd, nginx reverse proxy, PostgreSQL with SQLAlchemy, Alembic migrations, and zero-downtime reloads.
## Why FastAPI
- Async-first (handles 10K+ concurrent connections)
- Pydantic for type-safe request/response models
- Auto-generated OpenAPI/Swagger docs at `/docs`
- 3-5× faster than Flask, same-league as Node.js Express
- Massive ecosystem (SQLAlchemy 2, Alembic, Celery, APScheduler)
Good fit: REST APIs, WebSocket services, ML inference endpoints. Less ideal for server-rendered HTML apps — use Django or Flask for those.
## Stack we're deploying
```
Client → nginx (443) → Gunicorn → 4× Uvicorn workers → FastAPI app → PostgreSQL
↑
Redis (cache/queue)
```
## Step 1 — Prepare VPS
```bash
# AlmaLinux 9
sudo dnf install -y python3.12 python3.12-devel python3-pip nginx postgresql-server postgresql-contrib redis git certbot python3-certbot-nginx
# Ubuntu 22.04+
sudo apt install -y python3.12 python3.12-venv python3-pip nginx postgresql redis git certbot python3-certbot-nginx
# Create app user
sudo useradd -r -m -s /bin/bash fastapi
sudo su - fastapi
```
## Step 2 — Sample FastAPI app
`~fastapi/app/main.py`:
```python
from contextlib import asynccontextmanager
from fastapi import FastAPI, Depends, HTTPException
from fastapi.responses import JSONResponse
from sqlalchemy.ext.asyncio import AsyncSession
from pydantic import BaseModel, EmailStr
import os
from .db import get_db, engine
from .models import User
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
print("Starting up")
yield
# Shutdown
await engine.dispose()
print("Shutting down")
app = FastAPI(
title="MyAPI",
version="1.0.0",
lifespan=lifespan,
)
class UserCreate(BaseModel):
email: EmailStr
name: str
class UserOut(BaseModel):
id: str
email: str
name: str
class Config: from_attributes = True
@app.get("/health")
async def health():
return {"status": "ok", "version": "1.0.0"}
@app.post("/users", response_model=UserOut)
async def create_user(payload: UserCreate, db: AsyncSession = Depends(get_db)):
user = User(email=payload.email, name=payload.name)
db.add(user)
await db.commit()
await db.refresh(user)
return user
@app.get("/users/{user_id}", response_model=UserOut)
async def get_user(user_id: str, db: AsyncSession = Depends(get_db)):
user = await db.get(User, user_id)
if not user:
raise HTTPException(404, "Not found")
return user
```
`~fastapi/app/db.py`:
```python
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
import os
DATABASE_URL = os.getenv("DATABASE_URL") # postgresql+asyncpg://...
engine = create_async_engine(DATABASE_URL, pool_size=10, max_overflow=5)
SessionLocal = async_sessionmaker(engine, expire_on_commit=False)
async def get_db():
async with SessionLocal() as session:
yield session
```
`~fastapi/app/models.py`:
```python
import uuid
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import String
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[str] = mapped_column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
email: Mapped[str] = mapped_column(String(255), unique=True)
name: Mapped[str] = mapped_column(String(100))
```
`~fastapi/requirements.txt`:
```
fastapi==0.114.0
uvicorn[standard]==0.30.6
gunicorn==22.0.0
sqlalchemy==2.0.35
asyncpg==0.29.0
alembic==1.13.2
pydantic[email]==2.8.2
python-dotenv==1.0.1
```
## Step 3 — Install + setup venv
```bash
cd ~fastapi
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
## Step 4 — PostgreSQL
```bash
# As root
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
sudo -u postgres psql <
| Tool | Best for | Complexity |
FastAPI BackgroundTasks | Short tasks triggered by request | Zero — built-in |
| APScheduler | Cron-like schedules in-process | Low |
| Celery + Redis | Heavy async work, multiple workers | Medium |
| Arq | Lightweight async task queue | Low |
Start with `BackgroundTasks` for simple needs; scale to Celery or Arq when you need retries + multiple worker machines.
## Common pitfalls
## FAQ
Q
Flask, FastAPI, or Django?
FastAPI for modern APIs (async, typed, OpenAPI). Django for full-stack with templates, admin, ORM. Flask if you're maintaining existing Flask apps.
Q
Uvicorn alone or Gunicorn + Uvicorn?
Uvicorn alone works for dev + light prod. Gunicorn adds process management, graceful reload, better logging — use it for production.
Q
Can I run this on DomainIndia shared hosting?
Shared cPanel's Setup Python App runs simple FastAPI apps (via Passenger). For async + multiple workers, use VPS.
Q
Asyncpg or psycopg3?
Asyncpg is faster but less feature-complete. Psycopg3 (async mode) is more versatile, supports synchronous adapters. For greenfield FastAPI: asyncpg.
Q
How many concurrent requests on a 2 GB VPS?
With 4 Uvicorn workers × 1000 connections each = 4K theoretical. Real-world with DB-backed API: 500-2000/sec. Bottleneck is usually Postgres.
FastAPI in production wants a solid VPS with PostgreSQL.
Order VPS