A production-ready Todo API implementing Domain-Driven Design (DDD) and Hexagonal Architecture principles
Features โข Architecture โข Quick Start โข API Documentation โข Testing
- Overview
- Features
- Architecture
- Technology Stack
- Project Structure
- Quick Start
- Configuration
- API Documentation
- Design Patterns
- Testing
- Contributing
- License
This project demonstrates a production-grade implementation of a Todo API using FastAPI with Domain-Driven Design (DDD) and Hexagonal Architecture (Ports & Adapters). It showcases best practices for building scalable, maintainable, and testable Python applications.
- ๐ฏ Domain-Centric: Business logic isolated from infrastructure concerns
- ๐ Pluggable: Easy to swap implementations (database, message queue, etc.)
- ๐งช Testable: High test coverage with isolated unit tests
- ๐ Scalable: Clean separation enables horizontal scaling
- ๐ก๏ธ Maintainable: Clear boundaries reduce coupling and technical debt
- โ CQRS Pattern - Separate read and write models
- โ Event-Driven Architecture - Domain events for loose coupling
- โ Unit of Work Pattern - Transactional consistency
- โ Repository Pattern - Data access abstraction
- โ Value Objects - Type-safe domain primitives
- โ Domain Events - Business event tracking
- โ API Versioning - Future-proof API design
- โ Exception Handling - Centralized error management
- โ Docker Support - Containerized deployment
- โ Type Safety - Full type hints with Python 3.12
This project follows the Hexagonal Architecture pattern, organizing code into three main layers:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Infrastructure Layer โ
โ (FastAPI, SQLAlchemy, Event Handlers, External APIs) โ
โโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Adapters
โโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Application Layer โ
โ (Use Cases, DTOs, Interfaces/Ports) โ
โโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Use Cases
โโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Domain Layer โ
โ (Entities, Value Objects, Domain Events, Repositories) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ฏ Domain Layer (Core Business Logic)
- Entities and Aggregates
- Value Objects
- Domain Events
- Repository Interfaces
- Business Rules and Invariants
โ๏ธ Application Layer (Use Cases)
- Command Handlers (Write Operations)
- Query Handlers (Read Operations)
- DTOs (Data Transfer Objects)
- Port Interfaces (UnitOfWork, EventBus)
๐ Infrastructure Layer (Technical Details)
- FastAPI REST endpoints
- SQLAlchemy ORM models
- Database repositories
- Event bus implementation
- Middleware and exception handlers
| Technology | Purpose | Version |
|---|---|---|
| FastAPI | Web framework | Latest |
| Python | Programming language | 3.12+ |
| PostgreSQL | Database | Latest |
| SQLAlchemy | ORM | Latest |
| Poetry | Dependency management | Latest |
| Docker | Containerization | Latest |
| Pydantic | Data validation | v2.0+ |
src/
โโโ domain/ # Core business logic
โ โโโ entities/ # Domain entities
โ โ โโโ todo.py # Todo aggregate root
โ โโโ value_objects/ # Immutable value types
โ โ โโโ todo_id.py # Unique identifier
โ โ โโโ todo_status.py # Status enum
โ โ โโโ priority.py # Priority enum
โ โโโ events/ # Domain events
โ โ โโโ base.py # Base event
โ โ โโโ todo_events.py # Todo-specific events
โ โโโ repositories/ # Repository interfaces
โ โ โโโ todo_repository.py
โ โโโ exceptions.py # Domain exceptions
โ
โโโ application/ # Use cases and DTOs
โ โโโ use_cases/
โ โ โโโ commands/ # Write operations (CQRS)
โ โ โ โโโ create_todo.py
โ โ โ โโโ update_todo.py
โ โ โ โโโ complete_todo.py
โ โ โโโ queries/ # Read operations (CQRS)
โ โ โโโ get_todo.py
โ โ โโโ list_todos.py
โ โโโ dto/ # Data transfer objects
โ โ โโโ todo_dto.py
โ โโโ interfaces/ # Port interfaces
โ โโโ unit_of_work.py
โ โโโ event_bus.py
โ
โโโ infrastructure/ # External adapters
โ โโโ api/ # FastAPI layer
โ โ โโโ v1/
โ โ โโโ endpoints/
โ โ โ โโโ todos.py
โ โ โโโ schemas.py
โ โ โโโ dependencies.py
โ โโโ persistence/ # Database layer
โ โ โโโ sqlalchemy/
โ โ โโโ models.py
โ โ โโโ repositories.py
โ โ โโโ read_repositories.py
โ โ โโโ unit_of_work.py
โ โ โโโ database.py
โ โโโ events/ # Event handling
โ โโโ event_bus.py
โ โโโ handlers.py
โ
โโโ config/ # Configuration
โ โโโ settings.py
โ
โโโ main.py # Application entry point
- Python 3.12+
- Poetry
- Docker & Docker Compose
- PostgreSQL (or use Docker)
-
Clone the repository
git clone https://github.com/mahdighadiriii/Fastapi-DDD-Hexagonal-Todo.git cd Fastapi-DDD-Hexagonal-Todo -
Install dependencies
poetry install
-
Start PostgreSQL (using Docker)
cd postgres docker-compose up -d -
Configure environment variables
cp .env.example .env # Edit .env with your database credentials -
Run migrations
poetry run alembic upgrade head
-
Start the application
poetry run uvicorn src.main:app --reload
-
Access the API
- API: http://localhost:8000
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
If you prefer pip over Poetry:
pip install -r requirements.txt
uvicorn src.main:app --reloadConfiguration is managed through src/config/settings.py using Pydantic settings.
# Database
DATABASE_URL=postgresql://user:password@localhost:5432/todo_db
# Application
APP_NAME=Todo API
VERSION=1.0.0
DEBUG=true
# API
API_V1_PREFIX=/api/v1POST /api/v1/todos
Content-Type: application/json
{
"title": "Complete project documentation",
"description": "Write comprehensive README",
"priority": "HIGH"
}GET /api/v1/todos/{todo_id}GET /api/v1/todos?status=PENDING&priority=HIGH&skip=0&limit=10PUT /api/v1/todos/{todo_id}
Content-Type: application/json
{
"title": "Updated title",
"description": "Updated description",
"priority": "MEDIUM"
}POST /api/v1/todos/{todo_id}/completeDELETE /api/v1/todos/{todo_id}Success Response (201 Created)
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"title": "Complete project documentation",
"description": "Write comprehensive README",
"status": "PENDING",
"priority": "HIGH",
"created_at": "2025-10-26T10:30:00Z",
"updated_at": "2025-10-26T10:30:00Z",
"completed_at": null
}Error Response (404 Not Found)
{
"detail": "Todo not found"
}Separates read and write operations for optimal performance and clarity.
- Commands:
create_todo.py,update_todo.py,complete_todo.py - Queries:
get_todo.py,list_todos.py
Abstracts data access logic from business logic.
# Domain interface
class TodoRepository(ABC):
@abstractmethod
async def add(self, todo: Todo) -> None:
passManages transactions and ensures consistency.
async with uow:
todo = await uow.todos.get(todo_id)
todo.complete()
await uow.commit()Decouples business logic through events.
class TodoCompletedEvent(DomainEvent):
todo_id: TodoId
completed_at: datetimeEncapsulates domain concepts with validation.
@dataclass(frozen=True)
class TodoId:
value: UUID# Run all tests
poetry run pytest
# Run with coverage
poetry run pytest --cov=src --cov-report=html
# Run specific test file
poetry run pytest tests/domain/test_entities.pytests/
โโโ domain/ # Domain layer tests
โโโ application/ # Use case tests
โโโ infrastructure/ # Infrastructure tests
โโโ conftest.py # Shared fixtures
# Build image
docker build -t fastapi-ddd-todo .
# Run container
docker run -p 8000:8000 fastapi-ddd-tododocker-compose up -d- Connection Pooling: SQLAlchemy manages database connections efficiently
- Async/Await: Non-blocking I/O for better concurrency
- Read Models: Optimized queries for read operations (CQRS)
- Caching: Can be easily integrated at the infrastructure layer
- Indexing: Database indexes on frequently queried fields
- Input validation using Pydantic
- SQL injection prevention via SQLAlchemy ORM
- Environment-based configuration
- CORS middleware configuration
- Exception handling without information leakage
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow PEP 8 style guide
- Add type hints to all functions
- Write docstrings for public APIs
- Include unit tests for new features
- Update documentation as needed
This project is licensed under the MIT License - see the LICENSE file for details.
Mahdi Ghadiri
- GitHub: @mahdighadiriii
- Project: Fastapi-DDD-Hexagonal-Todo
โญ If you find this project helpful, please consider giving it a star!
Made with mahdiโค๏ธ using FastAPI and Domain-Driven Design