Synvro.Modulus.Observability
1.5.0
dotnet add package Synvro.Modulus.Observability --version 1.5.0
NuGet\Install-Package Synvro.Modulus.Observability -Version 1.5.0
<PackageReference Include="Synvro.Modulus.Observability" Version="1.5.0" />
<PackageVersion Include="Synvro.Modulus.Observability" Version="1.5.0" />
<PackageReference Include="Synvro.Modulus.Observability" />
paket add Synvro.Modulus.Observability --version 1.5.0
#r "nuget: Synvro.Modulus.Observability, 1.5.0"
#:package Synvro.Modulus.Observability@1.5.0
#addin nuget:?package=Synvro.Modulus.Observability&version=1.5.0
#tool nuget:?package=Synvro.Modulus.Observability&version=1.5.0
Modulus Framework
<p align="center"> <img src="logo.png" alt="Modulus logo" width="160" /> </p>
An enterprise-grade modular monolith framework for .NET 10, built with an explicit-registration module system, CLI scaffolding, a transactional outbox/inbox, and first-class multi-tenancy.
Overview
Modulus is designed for teams who need the architectural rigour of ABP or eShop
without the heavyweight abstractions. It provides proven building blocks that
compose cleanly — pick only what your application needs. The framework ships as
44 focused NuGet packages (published as Synvro.Modulus.*; the analyzer is packed
inside Synvro.Modulus.AspNetCore) plus a dotnet tool CLI for scaffolding complete
solutions, modules, and CRUD code.
Solution layout
src/ 45 projects across:
core/ Modulus.Core (abstractions+impl merged), Modulus.AspNetCore
analyzers/ Modulus.Analyzers (Roslyn MOD0001/MOD0002/MOD0003; packed in Modulus.AspNetCore)
data/ Modulus.Data.Abstractions, Modulus.EntityFrameworkCore,
EF Core providers (SqlServer, PostgreSQL, MySQL, SQLite), Data.MongoDB
identity/ Modulus.Identity (OpenIddict server, 6 IdP adapters, EF Core mapping,
SAML, LDAP, passkeys, sessions, SCIM 2.0)
messaging/ Modulus.Events, Modulus.Mediator, Modulus.Inbox (+ MongoDB),
Modulus.Outbox, Modulus.Outbox.Abstractions (kept: circular-dep seam),
Modulus.Outbox.Management, Modulus.Outbox.MongoDB, EventBus.RabbitMQ,
EventBus.Kafka, Modulus.Sagas (Rebus), Modulus.Webhooks (signed outgoing
webhooks), Modulus.Realtime (SSE / SignalR) + Realtime.Redis
platform/ Modulus.Platform (MultiTenancy, Authorization, BackgroundJobs, Caching,
Storage, SignalR, Networking), opt-in providers: Storage.S3,
Storage.AzureBlobs, Caching.Redis, SignalR.Backplane,
MultiTenancy.EntityFrameworkCore, Authorization.EntityFrameworkCore,
Authorization.Management, AuditLogging.EntityFrameworkCore,
AspNetCore.Redis (idempotency store), BackgroundJobs.Quartz,
Bff (per-client backends on YARP), Grpc,
GraphQL (GraphQL.NET)
ai/ Modulus.AI.Connector (external AI platform connector), .EntityFrameworkCore
(change journal), .Testing (conformance kit)
observability/ Modulus.Observability (Diagnostics + OpenTelemetry merged)
testing/ Modulus.Testing (WebApplicationFactory harness), Modulus.Testing.Architecture
cli/ Modulus.Cli (Spectre.Console.Cli scaffolding tool)
tests/ 42 projects
unit/ xUnit + NSubstitute + FluentAssertions (Category=Unit)
integration/ xUnit + Testcontainers (Docker required; Category=Integration)
benchmarks/ BenchmarkDotNet (Modulus.Benchmarks)
Getting started
Prerequisites
- .NET SDK 10.0.109 or newer (
dotnet --version) - Docker (only for the Testcontainers-based integration tests)
Create a new application
The Synvro.Modulus.* packages are published to nuget.org on release
(tags v* via .github/workflows/release.yml, requires NUGET_API_KEY),
but you can also use a local feed built from this repo. Pack the local
feed first, then install the CLI tool and scaffold a complete modular-monolith
solution:
# Pack and install the CLI tool
dotnet pack modulus.slnx -c Release -o ./nupkg
dotnet tool install -g --add-source ./nupkg Synvro.Modulus.Cli
# Generate a new application (SQLite by default) and run it.
# --package-source wires the generated NuGet.config's modulus-local source
# (with Synvro.Modulus.* source mapping) to your local feed; omit it once the
# framework version you need is on nuget.org.
modulus app MyApp --package-source "<abs-path-to>/nupkg"
cd MyApp
dotnet restore
dotnet run --project src/API/MyApp.Api
CLI commands
The modulus CLI (Spectre.Console.Cli + Scriban) is a dotnet tool that
generates complete solutions, modules, commands, queries, and CRUD code:
| Command | Description |
|---|---|
modulus app <name> |
Creates a modular-monolith solution (Host + Shared kernel + example module + tests) |
modulus module <name> |
Creates a blank 4-layer business module |
modulus add-module <name> |
Adds a module to an existing app + wires Program.cs registration + ProjectReference |
modulus generate-crud <Entity> --module M |
Generates entity, repo, DTOs, command/query handlers, controller |
modulus generate-command <Name> --module M |
Generates a single command + handler |
modulus generate-query <Name> --module M |
Generates a single query + handler |
modulus migrate add <Name> |
Scaffolds an EF Core migration in each module's Infrastructure project |
modulus migrate update |
Applies pending migrations to each module's database |
Each generated module uses a 4-layer Clean-Architecture layout
({App}.Modules.{Module}.{Domain,Application,Infrastructure,Presentation}) with
a per-module DbContext, per-module IUnitOfWork, and DTOs/integration events
living under Application/Dtos and Application/IntegrationEvents.
Templates are embedded Scriban resources under cli/Templates/.
Sample application
samples/TradeFlow— a reference application (18 modules, 77 projects) demonstrating the framework's recommended shape: module system, CQRS viaModulus.Mediator, per-module EF Core persistence, Serilog, Sentry, multi-tenancy, and authentication. Ships aNuGet.configpointing at the sample-localnupkg/feed (withSynvro.Modulus.*source mapping), so it builds straight afterdotnet pack modulus.slnx -c Release -o samples/TradeFlow/nupkg. Also includes Dockerfile, docker-compose.yml, and GitHub Actions CI.
Module system
Modules implement IModule or inherit from ModulusModule and are registered
explicitly in Program.cs. AddModulus(configuration, configure) invokes a
ModulusBuilder callback where each module is added in order — registration
order is authoritative for every lifecycle phase (no dependency-attribute
discovery, no startup module).
public sealed class ShopModule : ModulusModule
{
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
// Register module-specific services
}
}
// Program.cs
builder.Services.AddModulus(builder.Configuration, modules => modules
.AddModule<IdentityModule>()
.AddModule<DataModule>()
.AddModule<ShopModule>());
Features
- Modular architecture — explicit-registration module system where
AddModulus(configuration, modules => modules.AddModule<T>()...)wires the app and registration order drives every lifecycle phase. - CQRS mediator —
ICommand<TResult>/IQuery<TResult>with open-generic pipeline behaviors (validation, logging, transaction). No MediatR dependency. - Domain-Driven Design —
AggregateRoot<TId>with domain-event collection,ValueObjectbase, specifications, auditing interfaces. - Transactional outbox — domain events implementing
IIntegrationEventare enqueued to the outbox within the same DB transaction viaModuleDbContext.SaveChangesAsync. A backgroundOutboxProcessorclaims rows atomically, retries with exponential backoff, and dead-letters after max retries. - Inbox dedup — idempotent message processing. All
IIntegrationEventHandler<T>registrations are wrapped with an atomic claim-by-EventId decorator (EF CoreEfInboxStoreor MongoDBMongoInboxStore) so redeliveries don't double-execute. - Multi-tenancy —
ICurrentTenantbacked byAsyncLocal<TenantInfo?>(flows into background jobs / consumers), resolution from header/claim/subdomain, per-tenant connection-string resolver, and soft-delete+tenant query filters onModuleDbContext. - OpenIddict identity — password, client-credentials, and refresh-token grants with deny-by-default credential validation, scope allow-listing, and 6 external IdP adapters (Auth0, Authentik, Azure AD, Duende, Keycloak, Okta) that validate bearer tokens locally via OIDC discovery (signature, issuer, lifetime).
- EF Core providers — SQL Server, PostgreSQL, MySQL, SQLite (EF Core 10), plus MongoDB for document storage.
- Event bus — RabbitMQ (topic exchange, auto-reconnect) and Kafka
(idempotent producer, consumer groups); all implement
IModuleBusand integrate with the outbox. - Sagas — Rebus-based long-running orchestration.
- Platform services — permission-based authorization, background job scheduler (in-memory default; replace with Quartz.NET or Hangfire for production multi-replica deployments), caching (memory, tag-based invalidation), file storage (local, S3, Azure Blob), and SignalR hub base classes.
- API hardening — rate limiting, API versioning, health probes
(
/health/live,/health/ready), CORS, security headers, idempotency keys, feature flags, secrets guard, at-rest PII encryption, forwarded-headers. - Observability — OpenTelemetry tracing wired to the mediator pipeline and module lifecycle; correlation-ID propagation. Add EF Core and HTTP instrumentation via their respective OpenTelemetry packages.
Build
dotnet build modulus.slnx
The solution compiles with 0 errors, 0 warnings (TreatWarningsAsErrors is
enabled globally). Central Package Management is used via
Directory.Packages.props.
Common commands
| Task | Command |
|---|---|
| Build (Debug) | dotnet build modulus.slnx |
| Run all tests | dotnet test modulus.slnx |
| Run unit tests | dotnet test modulus.slnx --filter "Category=Unit" |
| Pack NuGet packages | dotnet pack modulus.slnx -c Release |
| Format check | dotnet format modulus.slnx --verify-no-changes |
Target framework
- .NET 10 (
net10.0) - SDK 10.0.109 or later
License
Apache License 2.0 — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Asp.Versioning.Mvc (>= 8.1.0)
- Asp.Versioning.Mvc.ApiExplorer (>= 8.1.0)
- ErrorOr (>= 2.1.1)
- FluentValidation (>= 12.1.1)
- FluentValidation.DependencyInjectionExtensions (>= 12.1.1)
- Microsoft.AspNetCore.OpenApi (>= 10.0.9)
- Microsoft.EntityFrameworkCore (>= 10.0.9)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.9)
- Microsoft.Extensions.Compliance.Abstractions (>= 10.7.0)
- Microsoft.Extensions.Compliance.Redaction (>= 10.7.0)
- Microsoft.Extensions.Telemetry (>= 10.7.0)
- Microsoft.Extensions.Telemetry.Abstractions (>= 10.7.0)
- Microsoft.FeatureManagement.AspNetCore (>= 4.6.0)
- Microsoft.OpenApi (>= 2.9.0)
- OpenTelemetry (>= 1.16.0)
- OpenTelemetry.Api (>= 1.16.0)
- OpenTelemetry.Exporter.Console (>= 1.16.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.16.0)
- OpenTelemetry.Extensions.Hosting (>= 1.16.0)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.16.0)
- OpenTelemetry.Instrumentation.Http (>= 1.16.0)
- OpenTelemetry.Instrumentation.Runtime (>= 1.15.1)
- Synvro.Modulus.AspNetCore (>= 1.5.0)
- Synvro.Modulus.Core (>= 1.5.0)
- Synvro.Modulus.Mediator (>= 1.5.0)
- ZiggyCreatures.FusionCache (>= 2.9.0)
- ZiggyCreatures.FusionCache.OpenTelemetry (>= 2.9.0)
-
net8.0
- Asp.Versioning.Mvc (>= 8.1.0)
- Asp.Versioning.Mvc.ApiExplorer (>= 8.1.0)
- ErrorOr (>= 2.1.1)
- FluentValidation (>= 12.1.1)
- FluentValidation.DependencyInjectionExtensions (>= 12.1.1)
- Microsoft.EntityFrameworkCore (>= 8.0.31)
- Microsoft.EntityFrameworkCore.Relational (>= 8.0.31)
- Microsoft.Extensions.Caching.Memory (>= 10.0.9)
- Microsoft.Extensions.Compliance.Abstractions (>= 10.7.0)
- Microsoft.Extensions.Compliance.Redaction (>= 10.7.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.9)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.9)
- Microsoft.Extensions.Diagnostics.HealthChecks (>= 10.0.9)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.9)
- Microsoft.Extensions.Options (>= 10.0.9)
- Microsoft.Extensions.Telemetry (>= 10.7.0)
- Microsoft.Extensions.Telemetry.Abstractions (>= 10.7.0)
- Microsoft.FeatureManagement.AspNetCore (>= 4.6.0)
- OpenTelemetry (>= 1.16.0)
- OpenTelemetry.Api (>= 1.16.0)
- OpenTelemetry.Exporter.Console (>= 1.16.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.16.0)
- OpenTelemetry.Extensions.Hosting (>= 1.16.0)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.16.0)
- OpenTelemetry.Instrumentation.Http (>= 1.16.0)
- OpenTelemetry.Instrumentation.Runtime (>= 1.15.1)
- Synvro.Modulus.AspNetCore (>= 1.5.0)
- Synvro.Modulus.Core (>= 1.5.0)
- Synvro.Modulus.Mediator (>= 1.5.0)
- ZiggyCreatures.FusionCache (>= 2.9.0)
- ZiggyCreatures.FusionCache.OpenTelemetry (>= 2.9.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.