Architecture

Overview

The Event Sourcing Reference Platform demonstrates a production-style cloud-native architecture built on Microsoft Azure using Event Sourcing, CQRS, and Domain-Driven Design (DDD).

Rather than serving as a proof of concept, this project has been designed to demonstrate architectural patterns commonly used in enterprise systems that require auditability, scalability, resiliency, and eventual consistency.


Architecture Principles

The solution has been designed around the following principles:


High-Level Architecture

Diagram coming soon


Request Lifecycle

A typical command follows the sequence below.

  1. User submits a command from the Angular application.
  2. ASP.NET Core validates the request.
  3. Command Handler loads the Aggregate.
  4. Aggregate executes business rules.
  5. One or more Domain Events are produced.
  6. Events are persisted to Azure Cosmos DB.
  7. Events are published to Azure Service Bus Topics.
  8. Projection Workers process new events.
  9. Azure SQL read models are updated.
  10. Queries retrieve optimized read models.

Architectural Patterns

Pattern Purpose
Event Sourcing Store immutable domain events rather than current state
CQRS Separate command and query responsibilities
Domain-Driven Design Encapsulate business logic inside aggregates
Event-Driven Architecture Decouple components using asynchronous messaging
Repository Pattern Abstract persistence concerns
Dependency Injection Improve modularity and testability
Eventual Consistency Optimise read performance independently from writes

Solution Architecture

                Angular Web Application
                         │
                         ▼
               ASP.NET Core Web API
                         │
                Command Handlers
                         │
                         ▼
                  Domain Aggregate
                         │
                  Domain Events
                         │
                         ▼
               Azure Cosmos DB
                  Event Store
                         │
                         ▼
                Azure Service Bus
                         │
              Projection Workers
                         │
                         ▼
               Azure SQL Database
                  Read Models
                         │
                         ▼
                  Query Handlers
                         │
                         ▼
                 Angular Web UI

Azure Services

Service Responsibility
Azure App Service Hosts API and web application
Azure Cosmos DB Event Store
Azure SQL Database Read model projections
Azure Service Bus Topics Event distribution
Azure Blob Storage Static assets and future event archival
Microsoft Entra ID Authentication and authorization
Application Insights Telemetry
Log Analytics Centralised logging
Azure DevOps Continuous Integration and Deployment
Bicep Infrastructure as Code

Design Decisions

Event Sourcing

Business state is derived from an immutable sequence of events rather than storing only the current state. This provides a complete audit history and supports event replay.

CQRS

Commands and queries are implemented independently. This allows transactional processing and reporting workloads to evolve separately.

Cosmos DB Event Store

Azure Cosmos DB provides scalable storage for immutable event streams while supporting optimistic concurrency for aggregate consistency.

SQL Read Models

Read models are projected into Azure SQL to support efficient querying, reporting and dashboard scenarios.

Service Bus

Azure Service Bus Topics distribute committed events to downstream consumers without tightly coupling projection processing to command execution.


Project Structure

docs/
├── architecture
│   ├── adr
│   ├── assets
│   └── decisions
├── assets
└── decisions
│
src/
└── Backend
│   └── building-blocks
│   │   └── BlastPlanning.Contracts
│   └── functions
│   │   └── BlastPlanning.ProjectionFunction
│   └── services
│       └── blast-planning
│           ├── BlastPlanning.Api
│           ├── BlastPlanning.Application
│           ├── BlastPlanning.Domain
│           └── BlastPlanning.Infrastructure
│
infra/
└── bicep/
│   └── environments
│   │   └── dev
│   └── modules
└── pipelines
│
tests/
    ├── Api.Tests/
    ├── Application.Tests/
    ├── Domain.Tests/
    └── Infratructure.Tests/

Scalability

The architecture allows each component to scale independently.


Observability

Operational visibility is provided through:


Security

Security considerations include:


Future Enhancements

Planned enhancements include: