A Complete Guide to FastAPI Project Structures

“FastAPI is one of the fastest-growing Python frameworks, loved for its simplicity, performance, and flexibility. But because FastAPI is unopinionated, there is no single “official” FastAPI project structures.

This is beneficialβ€”it gives you freedom.

But it’s also challengingβ€”how do you know which structure is right?

So, it’s important for backend developers to understand project structure, which is the architecture of the application. We will cover DDD and Clean Architecture, and how we can create a project design based on Clean Architecture. For starters like me, it is very confusing, as many tutorials don’t teach which project structure is recommended and when to use it.

In this guide, we’ll learn:

  1. Example folder layouts for each”Let’s dive in.
  2. The most commonly used FastAPI project structures
  3. How horizontal (layered) architecture works
  4. How vertical (feature-based) architecture works
  5. When to choose one over the other

Mine FastAPI project structures

Im learning FastAPI, I’m following Clean Architecture principles as much as possible and below is mine project structure.

Mine project structure follows a horizontal (layered) organization, which is a common approach for implementing the principles of Clean Architecture and i know its need lots of improvement.

app/
β”œβ”€β”€ config.py
β”œβ”€β”€ routes/
β”œβ”€β”€ repository/
β”œβ”€β”€ schemas/
β”œβ”€β”€ services/
└── db/
    β”œβ”€β”€ models/
    β”œβ”€β”€ database.py
    β”œβ”€β”€ db.db
    └── init_db.py

πŸš€ Improvements suggestion from chatgpt

As searching through chatgpt, got following suggestion of improvement of the project structure.

1. Separate core config from app logic: Common pattern for FastAPI, Flask, Django

app/core/config.py

2. Organize routes using β€œversions”: Easier for API evolution.

app/api/v1/users.py
app/api/v1/auth.py
app/api/router.py

3. db/structure refinement

Rename database.py β†’ session.py. Keep Base in a dedicated base.py to avoid import cycles.

app/db/session.py      # engine, SessionLocal, get_db()
app/db/base.py         # Base and import models

Place db.db inside /data/ or root, not inside source code.

project/data/db.db
  1. init_db.py only for dev

Creating tables using create_all() is okay only for development. In production, use Alembic migrations.


⭐ Why Project Structure Matters

Choosing the right structure affects:

  • Scalability
  • Maintainability
  • Onboarding new developers
  • Testing
  • Code clarity
  • Separation of concerns

A good structure ensures that as your application grows, it does not become a tangled mess.


1. 🧱 Horizontal / Layered Architecture (Most Common)

This structure organizes your project by technical layers, not by domain or feature, here is full details of horizontal architecture.

Example:

project/
β”‚
β”œβ”€β”€ .env
β”œβ”€β”€ main.py
β”œβ”€β”€ alembic/                # (Optional but recommended for DB migrations)
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ core/               # Core configuration and initialization
β”‚   β”‚   β”œβ”€β”€ config.py       # Pydantic Settings, app config
β”‚   β”‚   β”œβ”€β”€ security.py     # Auth utilities (JWT/OAuth2)
β”‚   β”‚   └── logging.py      # Centralized logging config
β”‚   β”‚
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ deps.py         # Common dependencies for routes
β”‚   β”‚   β”œβ”€β”€ v1/
β”‚   β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”‚   β”œβ”€β”€ users.py     # One file per domain route
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.py
β”‚   β”‚   β”‚   └── items.py
β”‚   β”‚   └── router.py        # APIRouter aggregator
β”‚   β”‚
β”‚   β”œβ”€β”€ db/
β”‚   β”‚   β”œβ”€β”€ base.py      # Base = declarative_base(), import all models here
β”‚   β”‚   β”œβ”€β”€ session.py       # engine, SessionLocal, get_db dependency
β”‚   β”‚   β”œβ”€β”€ init_db.py       # create_all (only for dev, not for prod)
β”‚   β”‚   └── models/
β”‚   β”‚       β”œβ”€β”€ user.py
β”‚   β”‚       β”œβ”€β”€ item.py
β”‚   β”‚       └── __init__.py
β”‚   β”‚
β”‚   β”œβ”€β”€ repositories/
β”‚   β”‚   β”œβ”€β”€ user_repo.py
β”‚   β”‚   β”œβ”€β”€ item_repo.py
β”‚   β”‚   └── __init__.py
β”‚   β”‚
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ user_service.py
β”‚   β”‚   β”œβ”€β”€ auth_service.py
β”‚   β”‚   └── __init__.py
β”‚   β”‚
β”‚   β”œβ”€β”€ schemas/
β”‚   β”‚   β”œβ”€β”€ user.py
β”‚   β”‚   β”œβ”€β”€ item.py
β”‚   β”‚   └── __init__.py
β”‚   β”‚
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”œβ”€β”€ helpers.py
β”‚   β”‚   └── email_utils.py
β”‚   β”‚
β”‚   └── __init__.py
β”‚
└── requirements.txt / pyproject.toml

This is the architecture used by many production FastAPI applications.

⭐ Why teams use it

  • Clear separation of concerns
  • Easy to test individual layers
  • Works well for small and medium apps
  • Familiar to developers from Django/Flask/Java backgrounds

⭐ Pros

βœ” Clean, predictable structure
βœ” Easy to read and navigate
βœ” Modules are decoupled
βœ” Good for CRUD-heavy apps
βœ” Ideal for monolithic services

⭐ Cons

✘ As your app grows, files become scattered
✘ Business logic can spread across multiple folders
✘ Adding new features often means editing many folders

⭐ When to choose Horizontal / Layered

Choose this architecture if:

  • Your app is small to medium-sized
  • You want maximum clarity and organization
  • You have few developers on the team
  • You value technical separation (e.g., controllers/services/repositories)
  • You’re building an internal API, CRM, admin tool, or SaaS backend

This is the most common structure for FastAPI.


2. πŸ“¦ Vertical / Feature-Based Architecture (Very Common for Large Apps)

Instead of organizing by layers, you organize by feature/domain.

Example:

app/
β”œβ”€β”€ users/
β”‚   β”œβ”€β”€ models.py
β”‚   β”œβ”€β”€ schemas.py
β”‚   β”œβ”€β”€ routes.py
β”‚   β”œβ”€β”€ repository.py
β”‚   β”œβ”€β”€ service.py
β”‚   └── __init__.py
β”‚
β”œβ”€β”€ auth/
β”‚   β”œβ”€β”€ routes.py
β”‚   β”œβ”€β”€ service.py
β”‚   β”œβ”€β”€ schemas.py
β”‚   └── models.py
β”‚
└── core/
    β”œβ”€β”€ config.py
    β”œβ”€β”€ database.py
    └── security.py

Each feature contains everything it needs. This approach is widely used in microservices, domain-driven design, and large enterprise systems.

⭐ Why teams use it

  • All files for a feature are kept together
  • Easy for multiple developers to work independently
  • Fewer cross-module imports
  • Features are modular and isolated

⭐ Pros

βœ” Perfect for large-scale applications
βœ” Each feature is self-contained
βœ” Easier refactoring
βœ” Easier to convert features into microservices later
βœ” Very clean boundaries

⭐ Cons

✘ Harder to maintain shared logic if not planned well
✘ Beginners may find it unfamiliar
✘ Can duplicate code across features
✘ Requires discipline to avoid cross-dependencies

⭐ When to choose Vertical / Feature-Based

Choose this architecture if:

  • Your application will grow large
  • You have many developers working in parallel
  • You want isolated modules
  • You’re following Domain Driven Design (DDD)
  • You may split the app into microservices later

This is the best architecture for enterprise-level FastAPI apps.


3. Minimal / Flat Structure (Good for learning)

For very small or prototype apps:

app/
β”œβ”€β”€ main.py
β”œβ”€β”€ routes.py
β”œβ”€β”€ models.py
β”œβ”€β”€ schemas.py
└── database.py

Great for:

  • Tutorials
  • Demos
  • MVPs

Not recommended for production.


Some teams combine both:

  • Shared layers for common logic
  • Feature folders for large modules

Example:

app/
β”œβ”€β”€ core/
β”œβ”€β”€ db/
β”œβ”€β”€ common/
β”‚   β”œβ”€β”€ utils.py
β”‚   └── dependencies.py
β”‚
β”œβ”€β”€ features/
β”‚   β”œβ”€β”€ users/
β”‚   β”œβ”€β”€ items/
β”‚   └── auth/

This is often the most practical structure for very large projects.


🧭 Which Architecture Should You Choose?

Here’s a quick cheat sheet:

App SizeTeam SizeBest Choice
Tiny / prototype1Minimal
Small1–3Layered (horizontal)
Medium3–10Layered or Hybrid
Large10+Vertical (feature-based) or Hybrid
MicroservicesAnyVertical

Related Artciles

  1. Introduction to FastAPI
  2. FastAPI Clean Architecture: A Developer’s Practical Guide
  3. Understanding the Relationship Between FastAPI, SQLAlchemy, ORM, and Database Connections
Scroll to Top