Skip to main content

Production-First, Not Tutorial-First

Most starter kits teach patterns. FullStackHero ships them. This is an opinionated, battle-tested foundation for building multi-tenant SaaS and enterprise APIs on .NET 10—wired, tested, and ready for production from day one.

Ship Faster

Get Identity, Multitenancy, Auditing, caching, mailing, jobs, storage, health checks, and OpenTelemetry out of the box

Modular by Design

Drop Modules.Identity, Modules.Multitenancy, Modules.Auditing into any API and let the module loader wire endpoints

Cloud-Ready

Aspire AppHost spins up Postgres + Redis + API with OTLP tracing enabled in seconds

Multi-Tenant from Day One

Finbuckle-powered tenancy across Identity and your module DbContexts with helpers to migrate and seed tenant databases

The FullStackHero Difference

1. Modular Monolith Architecture

Not microservices. Not a traditional layered architecture. A modular monolith is a single deployment unit with multiple bounded contexts that communicate via contracts.
From src/.claude/rules/architecture.md:12-22:
Single deployment unit

Multiple bounded contexts (modules)

Each module is self-contained

Communication via Contracts (interfaces/DTOs)
Why this matters:
  • Start simple, scale when needed: Deploy as a monolith in early stages, extract to microservices only when traffic/team size demands it
  • Shared transaction boundaries: Multi-entity operations without distributed transactions
  • Easier debugging: Single process, single codebase, full stack traces
  • Lower operational complexity: No service mesh, no distributed tracing setup required (though OpenTelemetry is ready when you need it)

2. Vertical Slice Architecture

Every feature is a complete, self-contained slice. No more hunting through layers. From src/Modules/Identity/Modules.Identity/Features/v1/Tokens/TokenGeneration/:
Features/v1/TokenGeneration/
├── GenerateTokenCommand.cs          # ICommand<TokenResponse>
├── GenerateTokenCommandHandler.cs   # ICommandHandler<GenerateTokenCommand, TokenResponse>
├── GenerateTokenCommandValidator.cs # FluentValidation rules
└── GenerateTokenEndpoint.cs         # Minimal API endpoint mapping
Benefits:
  • High cohesion: All code for one feature lives together
  • Low coupling: Features don’t depend on each other
  • Easy onboarding: New developers find everything in one folder
  • Refactoring confidence: Change one feature without breaking others

3. Production-Grade Building Blocks

From src/BuildingBlocks/Web/Extensions.cs:29-87, the platform wires:
1

Structured Logging

Serilog with OpenTelemetry sink, correlation IDs, machine name, thread ID enrichment
"Enrich": [
  "FromLogContext",
  "WithMachineName",
  "WithThreadId",
  "WithCorrelationId"
]
From src/Playground/Playground.Api/appsettings.json:35
2

OpenTelemetry

Tracing, metrics, and logs with OTLP export to Aspire dashboard or your observability backend
"OpenTelemetryOptions": {
  "Enabled": true,
  "Tracing": { "Enabled": true },
  "Metrics": {
    "Enabled": true,
    "MeterNames": [
      "FSH.Modules.Identity",
      "FSH.Modules.Multitenancy",
      "FSH.Modules.Auditing"
    ]
  }
}
From src/Playground/Playground.Api/appsettings.json:2-9
3

Authentication & Authorization

ASP.NET Identity with JWT issuance/refresh, roles, permissions, rate-limited auth endpointsFrom src/Modules/Identity/Modules.Identity/Features/v1/Tokens/TokenGeneration/GenerateTokenCommandHandler.cs:60-74:
// Validate credentials
var identityResult = await _identityService
    .ValidateCredentialsAsync(request.Email, request.Password, cancellationToken);

if (identityResult is null)
{
    // Audit failed login BEFORE throwing
    await _securityAudit.LoginFailedAsync(
        subjectIdOrName: request.Email,
        clientId: clientId!,
        reason: "InvalidCredentials",
        ip: ip,
        ct: cancellationToken);

    throw new UnauthorizedAccessException("Invalid credentials.");
}
4

Distributed Caching

Redis-backed cache with memory fallback
"CachingOptions": {
  "Redis": "localhost:6379"
}
From src/Playground/Playground.Api/appsettings.json:74-76
5

Background Jobs

Hangfire with PostgreSQL persistence
"HangfireOptions": {
  "Username": "admin",
  "Password": "Secure1234!Me",
  "Route": "/jobs"
}
From src/Playground/Playground.Api/appsettings.json:77-81
6

Health Checks

Readiness and liveness probes for KubernetesFrom src/BuildingBlocks/Web/Extensions.cs:63:
builder.Services.AddHealthChecks()
    .AddCheck("self", () => HealthCheckResult.Healthy());

4. Multi-Tenancy Out of the Box

From src/.claude/rules/architecture.md:94-113:
// Tenant-aware entity
public class Order : BaseEntity, IMustHaveTenant
{
    public Guid TenantId { get; set; }  // Auto-filtered by Finbuckle
}
Tenant Resolution Order:
  1. HTTP header: tenant (e.g., tenant: acme-corp)
  2. JWT claim: tenant
  3. Host/route strategy (optional)

5. Real-World Patterns

From src/Modules/Identity/Modules.Identity/Features/v1/Users/SearchUsers/SearchUsersEndpoint.cs:17-18:
return endpoints.MapGet(
    "/users/search",
    async ([AsParameters] SearchUsersQuery query,
           IMediator mediator,
           CancellationToken cancellationToken) =>
        await mediator.Send(query, cancellationToken))
    .WithName("SearchUsers")
    .WithSummary("Search users with pagination")
    .RequirePermission(IdentityPermissionConstants.Users.View);
Uses Mediator library (not MediatR). Commands/queries return ValueTask<T> instead of Task<T> for better performance.

Comparing Alternatives

Clean Architecture:
  • Horizontal layers (Domain, Application, Infrastructure, Presentation)
  • Features scattered across layers
  • Shared “Services” folder becomes a dumping ground
FullStackHero:
  • Vertical slices (one folder per feature)
  • Command/Query/Handler/Validator/Endpoint together
  • No shared services layer
Winner: FullStackHero for maintainability and feature isolation
Microservices:
  • Multiple deployments, service mesh, distributed tracing setup
  • Network calls between services (latency, partial failures)
  • Complex local development (Docker Compose with 10+ containers)
FullStackHero:
  • Single deployment (start with dotnet run)
  • In-process calls (fast, reliable)
  • Simple local dev (Aspire handles Postgres + Redis)
Winner: FullStackHero for early-stage products. Migrate to microservices when traffic/team size demands it.
VSA (Jimmy Bogard):
  • Great pattern, requires manual setup
  • No multi-tenancy story
  • No observability, caching, or job primitives
FullStackHero:
  • VSA + production infrastructure
  • Multi-tenancy built-in
  • OpenTelemetry, Redis, Hangfire, mailing pre-wired
Winner: FullStackHero for production readiness
ABP Framework:
  • Heavyweight, opinionated on UI (Angular/Blazor/MVC)
  • Module system requires ABP CLI
  • Commercial modules behind paywall
FullStackHero:
  • Lightweight, API-first (bring your own UI)
  • Standard .NET projects, no custom CLI
  • All modules open source (MIT license)
Winner: FullStackHero for API-first teams

Real-World Use Cases

Multi-Tenant SaaS

Each customer gets isolated data via IMustHaveTenant. Tenant provisioning, migrations, and status management via the Multitenancy module.Example: Project management SaaS where each company is a tenant

Enterprise APIs

Identity module provides users, roles, permissions, groups. Auditing module tracks every security event and exception.Example: Internal HR system with compliance requirements

E-Commerce Platforms

Add a Catalog module with vertical slices for products, categories, inventory. Use Jobs for order processing and Mailing for receipts.Example: Multi-vendor marketplace

Workflow Automation

Leverage Hangfire for long-running workflows, domain events for inter-module communication, and auditing for compliance trails.Example: Approval workflows with email notifications

Tech Stack Highlights

From src/.claude/rules/architecture.md:217-230:

.NET 10

Latest LTS with native AOT, improved performance, and C# 13

EF Core 10

PostgreSQL provider by default, SQL Server ready

Mediator

CQRS with ICommand<T> and IQuery<T> (not MediatR)

FluentValidation

Input validation with clean, testable rules

Hangfire

Background jobs with PostgreSQL persistence

Finbuckle

Multi-tenancy with automatic query filtering

Scalar

Beautiful OpenAPI docs (better than Swagger UI)

Serilog

Structured logging with OpenTelemetry sink

Aspire

Local orchestration for Postgres + Redis + API

Philosophy

From src/CLAUDE.md:138:
This is a production-ready starter kit. Every pattern is battle-tested. Follow the conventions, and you’ll ship faster.
FullStackHero is maintained by Mukesh Murugan for teams that want to ship faster without sacrificing architecture discipline.

Ready to Start?

Get a working API running in under 5 minutes with the Quickstart guide

Build docs developers (and LLMs) love