Instruction file imported from dsquire/npscli (
.github/instructions/fastapi.instructions.md). Copyright stays with the author.
my_fastapi_project/ ├── app/ │ ├── init.py │ ├── main.py │ ├── api/ │ │ ├── init.py │ │ ├── v1/ │ │ │ ├── init.py │ │ │ ├── users.py │ │ │ ├── posts.py │ ├── models/ │ │ ├── init.py │ │ ├── user.py │ │ ├── post.py │ ├── middleware/ │ │ ├── init.py │ │ ├── auth_middleware.py │ │ ├── logging_middleware.py │ │ └── cors_middleware.py │ ├── config.py │ ├── database.py │ └── utils.py ├── tests/ │ ├── init.py │ ├── test_users.py │ ├── test_posts.py ├── .env ├── requirements.txt ├── Dockerfile └── README.md
Best Practices Application Structure
Organize code into modular directories: api/, models/, middleware/, etc.
Place middleware logic in a dedicated middleware/ directory for clarity and maintainability.
Use versioned API subfolders (e.g., api/v1/) to support future upgrades.
Separate configuration, database, and utility logic into their own modules.
Security
Use robust authentication and authorization (e.g., OAuth2, JWT).
Implement rate limiting to protect against abuse.
Rigorously validate all input using Pydantic models.
Configure CORS to restrict allowed origins.
Always deploy behind HTTPS to secure data in transit.
Store secrets and sensitive settings in environment variables, not code.
Complimentary Packages and Frameworks
Pydantic: For data validation and settings management.
SQLAlchemy or Tortoise ORM: For database interactions.
Alembic: For database migrations.
Uvicorn or Hypercorn: High-performance ASGI servers.
pytest (with httpx): For asynchronous testing.
Ruff or Flake8: For linting and code quality.
Loguru or structlog: For advanced logging.
Sentry or Prometheus: For monitoring and error tracking.
Docker: For containerization and deployment.
Development Practices
Prefer async endpoints and dependencies for I/O-bound operations.
Use FastAPI’s dependency injection for reusable, testable components.
Leverage automatic OpenAPI/Swagger documentation for your API.
Write comprehensive tests from the start.
Manage configuration with Pydantic’s BaseSettings and .env files.
Implement global exception handlers for standardized error responses.
Organize and version your API endpoints for backward compatibility.
Deployment
Use production-grade ASGI servers (e.g., Uvicorn with Gunicorn workers).
Deploy behind a reverse proxy (e.g., Nginx) for SSL termination and load balancing.
Monitor application health and performance in production.
Structuring a FastAPI application effectively is crucial for maintainability, scalability, and ease of collaboration. Below are best practices and recommended project structures based on industry standards and top-performing companies. Core Principles for FastAPI Structure
Modularity: Organize code by domain or feature, not by file type. This makes the application easier to scale and maintain as it grows
.
Separation of Concerns: Keep business logic, data models, API routes, and utility functions in distinct modules
.
Consistency: Use clear, descriptive directory and file names to make the project intuitive for new developers
.
Scalability: Design the structure to accommodate future growth, such as adding new features or API versions
.
Recommended Project Structure
A widely adopted structure for FastAPI projects is:
my_fastapi_project/ ├── app/ │ ├── init.py │ ├── main.py # Entry point, initializes FastAPI app │ ├── api/ │ │ ├── init.py │ │ ├── v1/ # API version 1 │ │ │ ├── init.py │ │ │ ├── users.py │ │ │ └── posts.py │ │ └── v2/ # API version 2 │ │ └── ... │ ├── models/ │ │ ├── init.py │ │ ├── user.py │ │ └── post.py │ ├── schemas/ # (Optional, if you prefer separate from models) │ │ └── ... │ ├── config.py # Application configuration │ ├── database.py # Database connection and setup │ └── utils.py # Utility functions ├── tests/ │ ├── init.py │ ├── test_users.py │ └── test_posts.py ├── .env # Environment variables ├── requirements.txt # Python dependencies ├── Dockerfile # (Optional) Containerization └── README.md
This structure is flexible and can be adapted based on project needs
. Domain-Driven Structure (Alternative)
For larger or more domain-focused applications, a domain-driven structure is recommended:
fastapi-project/ ├── alembic/ # Database migrations ├── src/ │ ├── auth/ │ │ ├── router.py │ │ ├── schemas.py # Pydantic models │ │ ├── models.py # DB models │ │ ├── dependencies.py # Dependencies for auth routes │ │ ├── config.py # Local configs │ │ ├── constants.py │ │ ├── exceptions.py # Domain-specific exceptions │ │ ├── service.py # Business logic │ │ └── utils.py │ ├── aws/ │ │ ├── client.py │ │ ├── schemas.py │ │ ├── config.py │ │ ├── constants.py │ │ └── utils.py │ ├── posts/ │ │ ├── router.py │ │ ├── schemas.py │ │ ├── models.py │ │ ├── dependencies.py │ │ ├── constants.py │ │ ├── exceptions.py │ │ ├── service.py │ │ └── utils.py │ ├── config.py # Global configs │ ├── models.py # Global models │ ├── exceptions.py # Global exceptions │ ├── pagination.py # Global utilities │ └── main.py # App entry point ├── tests/ │ ├── auth/ │ ├── aws/ │ └── posts/ ├── templates/ │ └── index.html ├── requirements/ │ ├── base.txt │ ├── dev.txt │ └── prod.txt ├── .env ├── .gitignore └── alembic.ini
This approach is inspired by Netflix's Dispatch and is highly scalable for monoliths or complex microservices
. Key Best Practices
Use APIRouter for Modular Routes: Organize endpoints by domain or feature using FastAPI's APIRouter for better maintainability
.
Leverage Pydantic for Data Validation: Use Pydantic models for request and response validation, and separate them from database models
.
Separate Business Logic: Keep business logic in service modules, not in routers or models
.
Environment and Configuration: Use environment variables and Pydantic's BaseSettings for configuration management
.
Testing: Write unit and integration tests, and keep them alongside the code they test
.
Dependencies: Use FastAPI's dependency injection for reusable and testable code
.
Documentation: Maintain clear, up-to-date documentation for each module and endpoint
.
Monitoring: Implement monitoring and analytics for production APIs to track usage and errors .
Example: FastAPI’s Official Recommendation
FastAPI itself suggests using multiple files and APIRouter for larger applications: from fastapi import FastAPI from .routers import users, items
app = FastAPI() app.include_router(users.router) app.include_router(items.router)
This modular approach is flexible and scalable.
Summary Table Structure Type When to Use Key Features Feature-based Small to medium projects api/, models/, config/, utils/ Domain-driven Large/complex projects src/ with domain folders, per-module Official FastAPI All sizes APIRouter, multiple files Actionable Improvements
Start with a modular structure (e.g., app/api/, app/models/) for most projects.
Switch to domain-driven if your project grows or becomes more complex.
Always use dependency injection and separate business logic from routes.
Keep tests close to the code they are testing.
Document your structure and conventions for your team.
By following these practices, you ensure your FastAPI application is robust, scalable, and easy to maintain