Building Portfolio Insights: Lessons from an Event‑Driven .NET Microservices Dashboard

Published: (December 16, 2025 at 10:59 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

Portfolio Insights – Personal Finance Dashboard

Built with .NET 8, RabbitMQ, gRPC, Docker (micro‑services architecture)

Overview

Portfolio Insights is a demonstration of a .NET 8 micro‑services‑based personal‑finance and analytics platform. It builds on the architectural patterns explored in my earlier E‑Commerce Microservices project, applying them to a number‑driven, analytics‑focused domain.

The application lets users:

  • Manage investment portfolios (assets & quantities)
  • Retrieve simulated market prices
  • Compute portfolio analytics asynchronously
  • Receive notifications when analytics are refreshed

All services are containerized and orchestrated via Docker Compose, showcasing a realistic end‑to‑end distributed system.

What I Learned

  • Event‑driven microservices
  • gRPC and HTTP communication
  • CQRS & layered architectures
  • Message‑based analytics pipelines
  • Vertical Slice & Clean Architectures
  • Container orchestration with Docker
  • Cross‑cutting concerns (validation, logging, health checks, custom exception handling)

Solution Architecture

The solution consists of eight projects, all at the same directory level:

ServiceResponsibilityData Store
Market Data ServiceSimulates & publishes market pricesSQLite / Redis / In‑memory
Portfolio ServiceOwns user portfolios & assetsPostgreSQL (Marten)
Analytics ServiceComputes metrics from portfolio & market eventsSQL Server (layered architecture)
Notification ServiceReacts to analytics results & stores notificationsSQLite
YARP API GatewaySingle entry point for all client traffic
Razor Pages Web ClientUI that consumes the system via the gateway
(Other supporting projects)Infrastructure, contracts, etc.

High‑Level Flow

  1. User adds/updates assets in their portfolio.
  2. Portfolio Service publishes a PortfolioUpdatedEvent.
  3. Analytics Service consumes the event, joins it with the latest market prices, and computes metrics.
  4. Analytics Service publishes an AnalyticsComputedEvent.
  5. Notification Service reacts and stores a user notification.
  6. The client queries the Analytics or Notification endpoints when the data is ready.

Communication Styles

  • gRPC – Low‑latency, request/response interactions (e.g., Portfolio Service → Market Data Service for current prices).
  • RabbitMQ + MassTransit – Event‑driven workflows (portfolio updates, market price changes, analytics computations).

Design Insights

Diagram First

Before writing code, I mapped out:

  • Data ownership per service
  • Synchronous vs. asynchronous interactions
  • State‑change propagation across the system

This upfront work prevented costly redesigns and clarified endpoint contracts.

Asynchronous UI Considerations

Because analytics are computed in the background, the Razor Pages client must:

  • Trigger commands that start background workflows
  • Display previously computed data while waiting
  • Refresh views once downstream services have processed events

Designing the UI forced me to think carefully about when to request data and which service should provide it.

Service‑Specific Storage

ServiceStorage ChoiceRationale
PortfolioPostgreSQL (Marten)Document‑store semantics for flexible portfolio shapes
AnalyticsSQL ServerRelational queries for complex metric calculations
Market DataSQLite / Redis / In‑memoryLight‑weight persistence for simulated price feeds
NotificationSQLiteSimple, durable storage for user alerts

The key principle: clarity of ownership outweighs strict consistency across services.

Running the Project

# Clone the repository
git clone https://github.com/yourusername/Portfolio-Insights.git
cd Portfolio-Insights

# Start all services with Docker Compose
docker compose up --build

The gateway will be reachable at http://localhost:5000, and the Razor Pages UI at http://localhost:5000/ui.

Final Thoughts

Portfolio Insights is a learning and portfolio project, but it represents a meaningful step forward in my understanding of modern .NET micro‑services:

  • Clear boundaries and explicit contracts are essential in event‑driven systems.
  • Early workflow diagramming saves time and reduces coupling.
  • Front‑end design must reflect the realities of asynchronous processing.
  • Docker Compose provides an excellent sandbox for reasoning about distributed systems as a whole.

Feel free to explore the code, spin up the containers, and experiment with the architecture!

Microservices, Asynchronous Communication, and System‑Level Design

If you’re exploring similar architectures, my biggest recommendation is simple: design the flows before the code. In event‑driven systems, that clarity makes all the difference.

What’s Next?

If this article gave you a clearer picture of how an event‑driven microservices architecture comes together in a real‑world .NET application, here are a few ways to continue exploring:

  • 📁 Explore the GitHub Repository – Review the full source code to see how the services, message flows, API Gateway, and Razor Pages client fit together. Following the code alongside the architecture diagrams is the best way to reinforce how synchronous and asynchronous communication work in practice.
  • 💡 Share the Architecture – If you know someone learning microservices, messaging, or distributed systems in .NET, share this project with them. It’s often easier to understand these concepts through a concrete, end‑to‑end example.
  • 🖥 Experiment and Extend – Clone the project and try evolving it. Add new events, introduce additional analytics, or adjust how the client reacts to asynchronous workflows. Small changes are a great way to deepen your understanding of event‑driven design.
  • 👍 Star the Repository – If you find the project useful, consider starring the repository. It helps others discover the project and supports continued sharing of practical architecture examples.

Working through projects like this builds intuition that goes beyond individual frameworks—helping you design systems that scale in complexity while remaining understandable.

Back to Blog

Related posts

Read more »

gRPC -Why use a Mock Server?

Why a Mock Server Is Needed for gRPC gRPC provides compact messages, efficient binary transport over HTTP/2, and first‑class support for multiple communication...