A minimal example demonstrating the Layered Architecture pattern in Python. It shows how to structure an application with a clear separation of concerns between presentation, business logic, data access, and domain layers, improving maintainability, scalability, and testability.
⚠️ Note: This project is for learning purposes only. It intentionally omits many production aspects (error handling, logging, validation, security, testing, etc.) to keep the focus on core architectural principles.
This example implements a simple Contact Manager application that demonstrates:
- Clean separation of concerns across architectural layers
- Swappable data stores (SQLite and MongoDB)
- Multiple presentation interfaces (REST API and CLI)
- Factory pattern for repository creation
- Dependency injection for loose coupling
Each layer interacts only with the one directly below it, enforcing clean boundaries and easier testability.
| Layer | Responsibility | Example |
|---|---|---|
| Presentation | Entry points for user interaction | FastAPI REST API, CLI via Typer |
| Services (Business Logic) | Core logic orchestration | ContactService |
| Repositories (Data Access) | Persistence abstraction | SQLite & MongoDB implementations |
| Models (Domain Entities) | Data definition & validation | Pydantic models |
The service layer here is intentionally left without abstractions to show that, depending on project needs, such layers may not require them. Some engineers prefer to abstract every layer for consistency; others apply abstraction only when variation or testing needs justify it. This example simply illustrates a practical approach, not a statement on which is universally better.
.
├── models/ # Domain models (Pydantic)
├── services/ # Business logic layer
├── repositories/ # Data access layer
│ ├── sqlite/ # SQLite implementation
│ ├── mongodb/ # MongoDB implementation
│ └── repository_factory.py # Factory for repository creation
├── db/ # Database connection management
├── presentation/ # User interfaces
│ ├── fastapi/ # REST API interface
│ └── cli/ # Command-line interface
├── Dockerfile
├── docker-compose.yml
├── Makefile # Simplified development commands
└── requirements.txt- Docker & Docker Compose (recommended)
- Python 3.11+ for local development
The project includes a Makefile to simplify running and testing. List available commands:
make helpStart FastAPI with MongoDB:
make api-mongo
# Access the API at http://localhost:8000
# Swagger UI: http://localhost:8000/docsStart FastAPI with SQLite:
make api-sqlite
# Access the API at http://localhost:8001
# Swagger UI: http://localhost:8001/docs| Method | Endpoint | Description |
|---|---|---|
POST |
/contacts |
Create a new contact |
GET |
/contacts |
List all contacts |
GET |
/contacts/some-report |
Example service-layer method (returns name initials) |
Switch between database implementations using environment variables:
| Variable | Description | Default |
|---|---|---|
DB_TYPE |
"sqlite" or "mongodb" |
sqlite |
MONGO_URI |
MongoDB connection string | mongodb://localhost:27017/ |
DB_NAME |
MongoDB database name | contacts_db |
DB_PATH |
SQLite file path | contacts.db |
📄 See .env.example for configuration examples.
Different sources may use varying terms for similar architectural concepts. Here's how they map in this project:
| Term | Also Known As | Description |
|---|---|---|
| Repositories | Persistence Layer, DAO | Handle database operations |
| Services | Application Layer, Use Cases | Contain business logic |
| Presentation | Controllers, Adapters, UI | User-facing entry points |
| Models | Entities, Domain Models, DTO | Data structures and validation |
There's no single “correct” terminology, adapt these concepts to your project's needs.
For a detailed explanation of the layered architecture pattern and the design decisions behind this example, see:
👉 Medium Article: How Layered Architecture Just Makes Sense. A Natural Way to Understand It
This project is provided for educational purposes under the MIT License. Use it freely as a reference, and remember to add error handling, security, testing, and production best practices before using it in real applications.