Skip to main content

What are Modules?

Modules are self-contained, vertically-sliced bounded contexts that encapsulate specific business capabilities. Each module owns its:
  • Domain models and business logic
  • Database schema via dedicated DbContext
  • HTTP endpoints using Minimal APIs
  • Dependency injection registration
  • Health checks and initialization
This modular monolith pattern provides microservice-like isolation while maintaining deployment simplicity.

The IModule Interface

Every module implements the IModule interface, which defines two core responsibilities:
namespace FSH.Framework.Web.Modules;

public interface IModule
{
    // DI/Options/Health/etc. — don't depend on ASP.NET types here
    void ConfigureServices(IHostApplicationBuilder builder);

    // HTTP wiring — Minimal APIs only
    void MapEndpoints(IEndpointRouteBuilder endpoints);
}

ConfigureServices

Registers all module dependencies, including:
  • Services and repositories
  • DbContext with connection pooling
  • Health checks
  • Options configuration
  • Background workers
  • Event handlers
Services registered here should not depend on ASP.NET Core HTTP types. Keep this layer focused on application infrastructure.

MapEndpoints

Configures HTTP routing using Minimal APIs:
  • API versioning
  • Route groups with base paths
  • Individual endpoints with authorization
  • Rate limiting

Module Registration

Modules are automatically discovered and loaded using assembly-level attributes:
// In AssemblyInfo.cs
[assembly: FshModule(typeof(IdentityModule), order: 100)]
[assembly: FshModule(typeof(MultitenancyModule), order: 200)]
[assembly: FshModule(typeof(AuditingModule), order: 300)]
The order parameter controls initialization sequence:
  • Lower numbers execute first
  • Identity (100) loads before Multitenancy (200)
  • Critical infrastructure modules load early

Loading Modules

The ModuleLoader discovers and initializes modules from assemblies:
using FSH.Framework.Web.Modules;
using FSH.Modules.Identity;
using FSH.Modules.Multitenancy;
using FSH.Modules.Auditing;

var builder = WebApplication.CreateBuilder(args);

// Specify module assemblies
var moduleAssemblies = new Assembly[]
{
    typeof(IdentityModule).Assembly,
    typeof(MultitenancyModule).Assembly,
    typeof(AuditingModule).Assembly
};

// Register module services
builder.AddModules(moduleAssemblies);

var app = builder.Build();

// Map module endpoints
app.UseHeroPlatform(p =>
{
    p.MapModules = true;
});

Module Lifecycle

1

Discovery

The ModuleLoader scans assemblies for FshModuleAttribute declarations and instantiates module classes.
2

Service Configuration

Each module’s ConfigureServices method is called in order, registering dependencies with the DI container.
3

Validation Registration

FluentValidation validators are automatically discovered from module assemblies.
4

Endpoint Mapping

After the app is built, MapEndpoints is called for each module to wire up HTTP routes.

Built-in Modules

FullStackHero includes three core modules:

Identity

Authentication, authorization, users, roles, permissions, and sessions

Multitenancy

Tenant provisioning, isolation, and management with database per tenant

Auditing

Security audits, activity logging, and exception tracking

Module Isolation

Modules maintain clear boundaries:
AspectApproach
DatabaseSeparate DbContext per module
ContractsShared via *.Contracts projects
EventsIntegration events for cross-module communication
DependenciesModules don’t directly reference each other
EndpointsPrefixed with module name (e.g., /api/v1/identity/*)
Avoid tight coupling between modules. Use integration events or contracts for inter-module communication.

Module Structure

A typical module follows this organization:
Modules.{ModuleName}/
├── AssemblyInfo.cs              # [FshModule] attribute
├── {ModuleName}Module.cs        # IModule implementation
├── Domain/                      # Entities, value objects
├── Data/                        # DbContext, configurations
├── Features/v1/                 # Vertical slices (CQRS)
│   └── {Feature}/
│       ├── {Action}Command.cs
│       ├── {Action}Handler.cs
│       ├── {Action}Validator.cs
│       └── {Action}Endpoint.cs
├── Contracts/                   # DTOs, interfaces for external use
└── Services/                    # Domain services

Health Checks

Modules register health checks during ConfigureServices:
builder.Services.AddHealthChecks()
    .AddDbContextCheck<IdentityDbContext>(
        name: "db:identity",
        failureStatus: HealthStatus.Unhealthy);
Access health status at /health endpoint.

Next Steps

Create Custom Module

Learn how to build your own modules from scratch

Identity Module

Explore authentication and authorization features

Build docs developers (and LLMs) love