A FastAPI project structured as a Modular Monolith following Clean Architecture and Domain-Driven Design (DDD) principles.
- Clean Architecture: Separation of concerns with clear layer boundaries
- Domain-Driven Design: Business logic is at the center of the application
- Modular Monolith: Each feature is isolated in its own module
- Multi-Database Support: Easily switch between PostgreSQL and MySQL
- Type Hints: Full type annotations for better developer experience
- Dependency Injection: Using FastAPI's built-in dependency injection system
- Exception Handling: Centralized error handling
- Repository Pattern: Database access is abstracted away
- SQLAlchemy ORM: Object-Relational Mapping for database interactions
- Pydantic Models: Request and response validation
- Docker Support: Run the application in containers
- CLI Tools: Command-line tools for database management
- Enhanced Logging: Structured logging with Loguru
project/
│
├── app/
│ ├── core/ # Core shared code (cross-cutting concerns)
│ │ ├── database.py # SQLAlchemy database engine and session
│ │ ├── database_factory.py # Factory for different database types
│ │ ├── db_utils.py # Database utility functions
│ │ ├── settings.py # App settings using Pydantic BaseSettings
│ │ ├── exceptions.py # Custom exceptions (global error handlers)
│ │ ├── security.py # For auth/security shared code
│ │ ├── logging.py # Logging configuration with Loguru
│ │ ├── utils.py # General utility functions
│ │ └── base.py # SQLAlchemy declarative base
│ │
│ ├── modules/ # Feature Modules (DDD style)
│ │ ├── items/ # Example Feature Module
│ │ │ ├── controllers/ # FastAPI routers (presentation layer)
│ │ │ │ └── item_controller.py
│ │ │ ├── services/ # Application/Business logic layer
│ │ │ │ └── item_service.py
│ │ │ ├── repositories/ # Data access layer
│ │ │ │ └── item_repository.py
│ │ │ ├── entities/ # Domain models (SQLAlchemy ORM)
│ │ │ │ └── item_entity.py
│ │ │ ├── dtos/ # Request/Response Schemas (Pydantic)
│ │ │ │ └── item_dto.py
│ │ │ └── __init__.py
│ │
│ ├── routers.py # Automatically discover and include all routers
│ ├── cli.py # Command-line interface tools
│ └── main.py # FastAPI app instance and startup logic
│
├── data/ # SQLite database files
├── env_samples/ # Sample environment files for different databases
├── logs/ # Application logs
├── migrations/ # Alembic database migrations
├── static/ # Static files
├── run.py # Script to run the application
├── Dockerfile # Docker configuration
├── docker-compose.yml # Docker Compose configuration
├── requirements.txt # Project dependencies
└── README.md # Project documentation
- Python 3.11+
- pip (Python package manager)
- Clone the repository
- Install dependencies:
pip install -r requirements.txtThe simplest way to run the application is using the provided run.py script, which allows you to specify the database driver and other settings:
# Run with PostgreSQL (default)
python run.py
# Run with MySQL
python run.py --db-driver mysql --db-user root --db-password password --db-name app_db
# Run without database support
python run.py --no-db
# Enable auto-reload and debug mode
python run.py --reload --debugWhen running with --no-db, the application will:
- Skip all database initialization
- Disable database-dependent modules and endpoints
- Return 503 Service Unavailable for database-dependent endpoints
- Provide a
/api/db-statusendpoint to inform about disabled database functionality
This mode is useful for:
- Running only non-database dependent features
- Testing the application without a database
- Developing and testing the API interface without database setup
You can also use the provided environment sample files:
# Copy the desired sample file
cp env_samples/sqlite.env .env
# Run the application
uvicorn app.main:app --reload# Build and run with Docker Compose
docker-compose up -dThe API will be available at http://localhost:8000
- OpenAPI documentation: http://localhost:8000/docs
- ReDoc documentation: http://localhost:8000/redoc
The application now has optional database support, which is disabled by default:
- Database support is available but disabled by default (DATABASE_ENABLED=False in settings)
- No tables are created automatically on application startup
- No migrations are needed or supported
- Supports PostgreSQL and MySQL databases
To enable database support:
- Set DATABASE_ENABLED=True in your .env file or in app/core/settings.py
- Make sure you have installed the required database dependencies from requirements.txt
- Configure your database connection settings (host, port, user, password, database name)
- Manually create tables using the provided utility functions when needed
You can create, drop, or reset database tables using the db_utils module:
from app.core.db_utils import create_tables, drop_tables, reset_database
# Create all tables defined in your SQLAlchemy models
create_tables()
# Drop all tables (WARNING: This will delete all your data)
drop_tables()
# Reset database (drop all tables and recreate them)
reset_database()You can switch between PostgreSQL and MySQL databases programmatically:
from app.core.db_utils import switch_to_postgres, switch_to_mysql
# Switch to PostgreSQL
switch_to_postgres(
db_name="my_database",
user="postgres",
password="postgres",
host="localhost",
port="5432"
)
# Switch to MySQL
switch_to_mysql(
db_name="my_database",
user="root",
password="password",
host="localhost",
port="3306"
)The project is structured with concentric layers:
- Entities: Domain models representing business objects
- Repositories: Data access abstraction
- Services: Business logic
- Controllers: HTTP interface
Each feature module is self-contained with its own:
- Controllers (API endpoints)
- Services (business logic)
- Repositories (data access)
- Entities (domain models)
- DTOs (data transfer objects)
This allows for:
- Independent development
- Clear boundaries
- Easy reasoning about the codebase
- Better separation of concerns
FastAPI's dependency injection system is used extensively:
- Database sessions
- Services
- Repositories
- Security utilities
Centralized error handling with custom exceptions:
- AppException (base exception)
- NotFoundException
- BadRequestException
- ConflictException
- UnauthorizedException
- ForbiddenException
This project is licensed under the MIT License.