Skip to main content

Expense Manager Service Architecture

The expense manager service is built with FastAPI, following Clean Architecture principles.

Folder Structure (Backend)​

expense-manager-service/
β”œβ”€β”€ .coveragerc # Test coverage config
β”œβ”€β”€ .dockerignore # Docker ignore file
β”œβ”€β”€ .env # Environment variables (for local development)
β”œβ”€β”€ .env.sample # Sample env file for reference
β”œβ”€β”€ .gitignore # Git ignore file
β”œβ”€β”€ Dockerfile # Dockerfile for containerizing the app
β”œβ”€β”€ mypy.ini # Mypy config (static type checking)
β”œβ”€β”€ pyproject.toml # Project metadata and dependencies
β”œβ”€β”€ pytest.ini # Pytest configurations
β”œβ”€β”€ README.md # Project documentation
β”œβ”€β”€ ruff.toml # Ruff config (linting)
β”œβ”€β”€ tox.ini # Tox config (testing in isolated environments)
β”œβ”€β”€ uv.lock # UV lock file (dependency management)
β”œβ”€β”€ app/ # Main application code
β”‚ β”œβ”€β”€ __init__.py
β”‚ β”œβ”€β”€ main.py # FastAPI app entrypoint
β”‚ β”œβ”€β”€ entities/ # Domain layer
β”‚ β”‚ β”œβ”€β”€ errors/ # Domain-specific errors
β”‚ β”‚ β”œβ”€β”€ models/ # Domain models
β”‚ β”‚ └── repositories/ # Repository interfaces
β”‚ β”œβ”€β”€ infrastructures/ # Infrastructure layer (external systems)
β”‚ β”‚ β”œβ”€β”€ inmemory_db/ # In-memory DB implementations (for testing/dev)
β”‚ β”‚ └── sqlite_db/ # SQLite DB implementations (for production)
β”‚ β”‚ └── models/ # SQLAlchemy models
β”‚ β”œβ”€β”€ routers/ # Presentation/API layer
β”‚ β”‚ β”œβ”€β”€ v1/ # API version 1
β”‚ β”‚ β”‚ β”œβ”€β”€ endpoints/ # FastAPI routers
β”‚ β”‚ β”‚ β”œβ”€β”€ mappers/ # Mappers between schemas and entities
β”‚ β”‚ β”‚ β”œβ”€β”€ schemas/ # Pydantic schemas
β”‚ β”‚ β”‚ β”œβ”€β”€ services.py # Dependency injection
β”‚ β”‚ β”‚ └── __init__.py
β”‚ β”‚ └── __init__.py
β”‚ β”œβ”€β”€ settings/ # Configuration layer
β”‚ β”‚ β”œβ”€β”€ base.py # Base settings
β”‚ β”‚ β”œβ”€β”€ config.py # Config loader
β”‚ β”‚ β”œβ”€β”€ dev.py # Development settings
β”‚ β”‚ └── __init__.py
β”‚ └── use_cases/ # Use Cases layer (Business logic)
β”‚ β”œβ”€β”€ errors/ # Use-case-specific errors
β”‚ └── models/ # Use-case-specific models
β”œβ”€β”€ docs/ # Documentation
β”œβ”€β”€ tests/ # Test cases
β”‚ β”œβ”€β”€ conftest.py # Pytest configurations at root
β”‚ β”œβ”€β”€ integration/ # Integration tests
| | β”œβ”€β”€ conftest.py # Pytest configurations at integration test level
β”‚ β”‚ └── routers/
β”‚ β”‚ └── v1/
β”‚ └── unit/ # Unit tests
β”‚ β”œβ”€β”€ conftest.py # Pytest configurations at unit test level
β”‚ β”œβ”€β”€ settings.py
β”‚ └── use_cases/

Layered Architecture & File-Level Details​

The backend follows Clean Architecture principles, with each layer mapped to specific folders and files:

Domain Layer (app/entities/)​

  • Purpose: Core business logic, domain models, and error definitions.
  • Key Files:
    • models/*: Define immutable business entities (e.g., AccountName).
    • models/base.py: Base entity with common fields (e.g., id).
    • errors/: Custom exceptions for domain errors (e.g., AccountNotFoundError).
    • repositories/: Abstract repository interfaces (e.g., AccountRepositoryInterface).

Use Cases Layer (app/use_cases/)​

  • Purpose: Application-specific business logic and orchestration.
  • Key Files:
    • Service classes encapsulating business use cases (e.g., AccountService).
    • models/: Use-case-specific models if needed.
    • errors/: Use-case-specific errors, distinct from domain errors.

Infrastructure Layer (app/infrastructures/)​

  • Purpose: External system integration, persistence, and adapters.
  • Key Files:
    • inmemory_db/: In-memory repository implementations for testing/dev.
    • sqlite_db/: SQLite repository implementations and DB config (e.g., accounts.py, database.py).

Presentation/API Layer (app/routers/)​

  • Purpose: API endpoints, request/response schemas, and routing.
  • Key Files:
    • v1/endpoints/: FastAPI routers for each resource (e.g., accounts.py).
    • v1/mappers/: Convert between schemas and entities. DTO not needed here as Schemas serve that purpose.
    • v1/schemas/: Pydantic schemas for API requests/responses.
    • v1/services.py: Dependency injection for repositories/services.

Configuration Layer (app/settings/)​

  • Purpose: Environment and application configuration.
  • Key Files:
    • base.py, dev.py, config.py: Settings for different environments, loaded via Pydantic.

Entrypoint​

  • main.py: FastAPI app initialization, middleware, and startup logic.

Tests​

  • tests/: Unit and integration tests for all layers.

Technology Stack & Rationale​

  • Python 3.13+: Backend technology.
  • FastAPI: High-performance, async web framework for building APIs.
  • Pydantic: Data validation and settings management.
  • SQLAlchemy (async): Async ORM for database access (SQLite).
  • Uvicorn: ASGI server for running FastAPI apps.
  • UV: Dependency management.
  • Mypy: Static type checking.
  • Pytest: Testing framework.
  • Tox: Testing in isolated environments.
  • Ruff: Linting and code quality.
  • Clean Architecture: Promotes separation of concerns, testability, and maintainability.
  • In-memory, SQLite & PostgreSQL Repositories: Support for both development/testing and production persistence.

Notes & Best Practices​

  • Dependency Rule: Outer layers (API, Infrastructure) depend on inner layers (Use Cases, Entities), never the reverse.
  • Extensibility: Add new features by extending the appropriate layer, maintaining separation of concerns.
  • Configuration: Environment-specific settings are managed in settings/ and .env files.
  • Testing: All tests are in tests/.
info

This structure ensures maintainability, testability, and clear separation of concerns as the service evolves.