System overview
The API follows a strict layered approach where each layer has clearly defined responsibilities and depends only on the layer directly below it:Component diagram
The architecture ensures that changing how Redis stores data never touches business logic, and swapping a currency provider only requires changes in the infrastructure layer.
Request flow
When you make a conversion request, the system follows this flow:Cache hit scenario
When a rate is already cached (within 5 minutes):Cache hits result in zero external API calls, providing instant responses and reducing costs.
Cache miss scenario
When no cached rate exists, the system aggregates from multiple providers:application/services/rate_service.py:69:
Dependency rules
The architecture enforces strict dependency rules:- API layer imports from
application/only - Application layer imports from
domain/andinfrastructure/ - Domain layer imports nothing from other project layers (pure Python)
- Infrastructure layer imports from
domain/only
Why these rules matter
Why these rules matter
These rules ensure that:
- Your domain logic remains framework-agnostic and easily testable
- Infrastructure changes don’t cascade through the codebase
- Business logic stays isolated from HTTP concerns
- You can swap databases or external APIs without touching core functionality
Key characteristics
Fault tolerant
Continues operation even if 1-2 providers fail, averaging remaining responses
Performance optimized
Parallel provider fetching and Redis caching minimize response times
Maintainable
Clear separation of concerns makes changes predictable and isolated
Observable
Rate history in PostgreSQL enables analytics and audit trails
Next steps
Layer responsibilities
Learn what each layer does and how they interact
Provider strategy
Understand multi-provider aggregation and fallback logic
Caching strategy
Explore Redis cache patterns and TTL values
Database schema
Review PostgreSQL tables and indexes
