DEV Community

Cover image for Building a Scalable Python Project with FastAPI and uv.
CodeWithDhanian
CodeWithDhanian

Posted on

Building a Scalable Python Project with FastAPI and uv.

In this tutorial, we’ll break down the anatomy of a scalable Python project using FastAPI and uv. The goal is to create a clean and maintainable structure that makes it easy to collaborate, onboard new developers, and deploy with confidence.

We’ll cover:

  • Setting up a clean folder structure
  • Managing configuration with .env
  • Adding centralized logging
  • Writing simple but effective tests
  • Using pyproject.toml and .python-version for consistency
  • Containerizing with Docker and orchestrating with docker-compose

1. Project Setup

First, let’s create a new directory for our project.

mkdir fastapi-scalable
cd fastapi-scalable
Enter fullscreen mode Exit fullscreen mode

We’ll use uv as our package manager.

uv init
Enter fullscreen mode Exit fullscreen mode

This creates a pyproject.toml file, which will manage dependencies and project metadata.

2. Folder Structure

A good folder structure makes your project easy to navigate and extend.

fastapi-scalable/
│── app/
│   ├── api/
│   │   ├── v1/
│   │   │   └── routes.py
│   ├── core/
│   │   ├── config.py
│   │   ├── logging.py
│   ├── models/
│   │   └── user.py
│   ├── services/
│   │   └── user_service.py
│   └── main.py
│
│── tests/
│   ├── test_routes.py
│
│── .env
│── .python-version
│── pyproject.toml
│── Dockerfile
│── docker-compose.yml
Enter fullscreen mode Exit fullscreen mode

3. Managing Configuration with .env

Centralize your environment variables in a .env file.

.env

APP_NAME=FastAPI Scalable Project
APP_ENV=development
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
Enter fullscreen mode Exit fullscreen mode

Load these variables using pydantic-settings in app/core/config.py:

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str
    app_env: str
    database_url: str

    class Config:
        env_file = ".env"

settings = Settings()
Enter fullscreen mode Exit fullscreen mode

4. Centralized Logging

Logging helps track errors and monitor the health of your app.

app/core/logging.py:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

logger = logging.getLogger("fastapi-scalable")
Enter fullscreen mode Exit fullscreen mode

Usage in routes:

from fastapi import APIRouter
from app.core.logging import logger

router = APIRouter()

@router.get("/")
def read_root():
    logger.info("Root endpoint accessed")
    return {"message": "Welcome to FastAPI Scalable Project"}
Enter fullscreen mode Exit fullscreen mode

5. Writing Tests

A simple test using pytest.

tests/test_routes.py:

from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_root():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Welcome to FastAPI Scalable Project"}
Enter fullscreen mode Exit fullscreen mode

Run tests:

pytest
Enter fullscreen mode Exit fullscreen mode

6. Using pyproject.toml and .python-version

Your pyproject.toml defines dependencies:

[project]
name = "fastapi-scalable"
version = "0.1.0"
dependencies = [
    "fastapi",
    "uvicorn",
    "pydantic-settings",
    "pytest",
]

[tool.uv]
python = "3.11"
Enter fullscreen mode Exit fullscreen mode

.python-version:

3.11
Enter fullscreen mode Exit fullscreen mode

This ensures consistency across environments.


7. Containerization with Docker

Dockerfile:

FROM python:3.11-slim

WORKDIR /app

COPY pyproject.toml .
COPY uv.lock .

RUN pip install uv && uv sync

COPY . .

CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Enter fullscreen mode Exit fullscreen mode

docker-compose.yml:

version: "3.9"

services:
  web:
    build: .
    ports:
      - "8000:8000"
    env_file: .env
    volumes:
      - .:/app
    depends_on:
      - db

  db:
    image: postgres:14
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
    ports:
      - "5432:5432"
Enter fullscreen mode Exit fullscreen mode

Run with:

docker-compose up --build
Enter fullscreen mode Exit fullscreen mode

Tip

You now have a scalable FastAPI project structure with configuration management, centralized logging, testing, and containerization. This setup makes it easy to extend features, onboard teammates, and deploy in consistent environments.

Top comments (0)