This project implements a cash flow control system designed to help merchants manage their daily transactions and consolidated balances.
The architecture follows modern principles of event-driven design (EDA), CQRS + Event Sourcing, and microservices, providing scalability, resilience, and flexibility.
It is fully containerized using Docker Compose, making it easy to set up and run locally or deploy to the cloud.
The system enables:
- Creating accounts
- Recording debit and credit transactions
- Generating and retrieving daily consolidated balances
- Querying current balances
All operations are designed to be idempotent, deterministic, and fault-tolerant. Authentication is handled externally by the API Gateway.
For detailed rationale, alternatives considered, and trade-offs behind key architectural choices — including microservices, RabbitMQ messaging, event sourcing, API Gateway, containerization, and observability — please refer to the Architecture Decision Records (ADRs).
- Pattern: Event-Driven Architecture (EDA) with CQRS and Event Sourcing
- Microservices:
AccountService
: Manages account creation and issues tokens.TransactionService
: Records debit/credit transactions.ConsolidationService
: Generates daily consolidations based on transactions.BalanceService
: Computes and provides the current balance.
- Saga Pattern:
- Uses Choreography-based Saga to manage distributed transactions across microservices, ensuring failure handling and rollback without a centralized orchestrator.
- API Gateway:
- Built with Kong, acts as a reverse proxy and enforces authentication.
- Message Broker:
- RabbitMQ for reliable asynchronous event delivery between services, using mutual TLS (mTLS) for secure communication.
- Implements the Dead Letter Pattern to handle undeliverable or failed messages gracefully.
- Datastores:
EventStoreDB
: Stores all events in an append-only log (via gRPC).MongoDB
: Stores projections (read models) for fast queries:- Transactions by AccountId & Date
- Consolidations by AccountId & Date
- Balance by AccountId
- Bounded Contexts:
- Each microservice represents a bounded context, fully owning its data and logic.
- Containerization & Orchestration:
- Each microservice runs inside its own Docker container.
- Containers are orchestrated by Kubernetes, enabling horizontal and vertical scaling based on demand, ensuring high availability and efficient resource utilization.
The system ensures that Transaction Service remains operational even if Consolidation Service becomes unavailable, supporting the business requirement of service independence.
For observability and monitoring, the following open-source tools are recommended:
- Sidecar: OpenTelemetry (for metrics, traces, and logs instrumentation)
- Metrics Backend: Prometheus + Grafana (for scraping, storing, and visualizing metrics)
- Distributed Tracing: Jaeger (for tracing request flows across services)
- Logging: Elasticsearch acts as the storage and search engine where logs and other telemetry data are indexed and stored. Kibana is the visualization and dashboard tool that connects to Elasticsearch to display, explore, and analyze those logs and telemetry data.
✅ Event Sourcing
✅ CQRS (Command Query Responsibility Segregation)
✅ Event-Driven Communication (RabbitMQ)
✅ Dead Letter Pattern for failed events
✅ Minimal APIs (lightweight .NET services)
✅ Idempotent command handling with deterministic streamId
control
✅ Disposable resources
✅ mTLS between services through the broker
✅ Docker Compose orchestration
✅ Only open source technologies were used, optimizing for low infrastructure and licensing costs.
- .NET 8 (LTS): Ensures long-term support, stability, and modern runtime performance.
- EventStoreDB: Native event sourcing database with gRPC.
- MongoDB: Document-based store for projections, high read performance.
- RabbitMQ: Proven message broker with support for mTLS and dead-letter queues.
- Kong Gateway: Cloud-native API gateway with authentication and rate-limiting.
- Docker Compose: Orchestration of all services for easy deployment and local development.
📋 Technology Decision Guidelines
Technology / Pattern | When to Use | When to Avoid | Integration Testing Considerations | Impact on Micro Frontend Creation |
---|---|---|---|---|
Microservices | Independent scalability, modular maintenance, isolated deployment | Small, simple systems with low complexity | High complexity, requires distributed testing | Facilitates independent frontend teams aligning with backend services |
Multiple Databases | Optimization for different data types and query patterns | When synchronization and maintenance complexity is prohibitive | Must validate consistency across different stores | Requires careful data synchronization strategies across front and back ends |
RabbitMQ (Event-Driven) | Asynchronous, decoupled, fault-tolerant communication | Systems requiring immediate consistency and synchronous communication | Async testing challenges, queue simulation required | Enables loosely coupled frontend-backend integration with event-driven updates |
Event Sourcing | Audit requirements, state reconstruction, complete change tracking | When event history overhead exceeds benefits | Event replay and consistency testing require special care | Complexity in syncing frontend state with event stream; demands careful UI event modeling |
CQRS | Separate command and query optimization for performance and scalability | Simple systems where separation adds unnecessary complexity | Must test separate read/write paths | Allows distinct read models useful for dynamic micro frontends |
Choreographed Saga | Event-driven distributed transaction coordination with maximum decoupling | Simple or centralized transactions where distributed complexity is unnecessary | Complex integration tests, event-based monitoring needed | Adds complexity in coordinating frontend state transitions across distributed services |
API Gateway (Kong) | Authentication, authorization, unified routing in microservices architectures | Monolithic or very simple systems | End-to-end tests depend on gateway layer | Central point for securing and routing API calls used by micro frontends |
Docker & Kubernetes | Orchestration, automated deployment, scalability in distributed environments | Small applications where operational overhead isn't justified | Benefits testing but adds complexity and execution time | Enables deployment and scaling of frontend components alongside backend microservices |
- Docker & Docker Compose installed
git clone https://github.com/andreymmonteiro/CashFlow.git
cd CashFlow
docker network create cashflow-net
docker compose up -d
cd Tests\NonFunctional.Tests.Load
docker compose up
Survey and Research Insights
As part of this project, a research paper titled "Event-Driven Architecture in High-Volume Microservices: A Survey on Industry Practices" was developed to validate and complement the findings of a prior systematic literature review.
This survey captures real-world practices, challenges, and trends from industry professionals regarding the application of event-driven architecture in large-scale microservices environments. The insights gained provide empirical evidence supporting key architectural decisions made in this project, such as the use of event sourcing, asynchronous communication, and distributed transaction patterns.
The paper serves as a bridge between academic research and practical implementation, reinforcing the relevance and effectiveness of the solution’s design choices.
📚 References
This solution follows best practices and is grounded in research findings from:
@article{silva2025guidelines, title={Guidelines for the Application of Event Driven Architecture in Micro Services with High Volume of Data}, author={Silva, Marcus VS and dos Santos, Luiz FC and Soares, Michel S and Rocha, Fabio Gomes}, year={2025} }
@article{dosmicrofront, title={Microfront-End: Systematic Mapping}, author={dos Santos, Luiz Felipe Cirqueira and Silva, Marcus Vinicius Santana and dos Santos, Shexmo Richarlison Ribeiro and Rocha, F{'a}bio Gomes and da Silva, Elisrenan Barbosa} }