FastAPI Blueprint 03: Core FastAPI Structure

Learn how to structure FastAPI apps for flexibility so you can plug in new features without breaking the system.

FastAPI Blueprint 03: Core FastAPI Structure
FastAPI Blueprint 03: Core FastAPI Structure

What You’ll Learn in This Chapter

By now, you have:

  • A working FastAPI app scaffold from Lesson 1
  • A clean environment and Docker setup from Lesson 2

In this chapter, we’ll:

  • Structure the app for modularity
  • Organize routes into versioned modules
  • Implement shared dependencies
  • Prepare the app for future features (auth, databases, Kafka) without rewriting core logic

By the end, you’ll have a production-ready FastAPI skeleton that’s easy to extend for any microservice.


Why Structure Matters in FastAPI

FastAPI is flexible, but if you throw all routes into main.py, your project will:

  • Get messy quickly
  • Make it harder to reuse code
  • Slow down onboarding for new devs

We’ll fix that by:

  • Grouping routes into versioned modules
  • Using dependency injection for reusability
  • Keeping main.py minimal (just an app factory)

Folder Structure Update

We’ll refine from Lesson 2 to introduce domain-driven structure:

app/
├─ api/
│  ├─ deps.py                 # Shared dependencies
│  ├─ v1/
│  │  ├─ __init__.py
│  │  ├─ routes_health.py     # System health/version
│  │  ├─ routes_users.py      # Example resource
│  │  └─ routes_items.py      # Example resource
├─ core/
│  ├─ config.py
│  ├─ logging.py
│  ├─ version.py
├─ domain/                    # Business logic
│  ├─ users.py
│  └─ items.py
├─ ports/
├─ adapters/
└─ main.py

Step-by-Step Build

1. Shared Dependencies

Dependencies help avoid repetitive code like DB connections or auth checks.

app/api/deps.py

from fastapi import Depends

# Example: current user dependency placeholder
def get_current_user():
    return {"username": "demo_user"}

2. Routes by Feature

We’ll create an example resource to show modularity.

app/api/v1/routes_users.py

from fastapi import APIRouter, Depends
from app.api.deps import get_current_user

router = APIRouter()

@router.get("/users/me", tags=["users"])
async def read_current_user(current_user: dict = Depends(get_current_user)):
    return current_user

app/api/v1/routes_items.py

from fastapi import APIRouter

router = APIRouter()

@router.get("/items", tags=["items"])
async def list_items():
    return [{"id": 1, "name": "Example Item"}]

3. API Router Assembly

We’ll gather all v1 routes in a single file for cleaner main.py.

app/api/v1/init.py

from fastapi import APIRouter
from .routes_health import router as health_router
from .routes_users import router as users_router
from .routes_items import router as items_router

api_router = APIRouter()
api_router.include_router(health_router)
api_router.include_router(users_router)
api_router.include_router(items_router)

4. Clean main.py

Your main.py now just wires settings, logging, and routes.

app/main.py

from fastapi import FastAPI
from app.core.config import settings
from app.core.logging import setup_logging
from app.api.v1 import api_router

def create_app() -> FastAPI:
    setup_logging(settings.log_level)

    app = FastAPI(
        title=settings.app_name,
        version="0.1.0",
        docs_url="/docs",
        redoc_url="/redoc",
    )

    app.include_router(api_router, prefix=settings.api_v1_str)

    return app

app = create_app()

5. Test It

Run locally:

poetry run uvicorn app.main:app --reload

Test endpoints:

curl http://127.0.0.1:8000/api/v1/health
curl http://127.0.0.1:8000/api/v1/users/me
curl http://127.0.0.1:8000/api/v1/items

Checklist for Chapter 3 Completion

  • api/v1 folder contains separate route files for each feature
  • deps.py created for shared dependencies
  • api_router collects all routes into one import for main.py
  • main.py contains no business logic — just app wiring
  • App runs and all endpoints respond correctly

Next Up – Lesson 4

In FastAPI Blueprint 04: Database Layer Abstraction, we’ll:

  • Implement a generic database port interface
  • Create adapters for PostgreSQL, MongoDB, and Redis
  • Show how to switch DBs via config, even run multiple in one service