We're committed to cloud-native architecture and microservices, but when you're building enterprise software for customers, you face a reality check: some customers want simple, one-click installations they can run on a single server, while others need cloud-native deployments that scale horizontally. Building separate monolithic and microservices versions of the same product isn't sustainable.
So we built Hosuto some years ago to solve this. It's a .NET library that lets you write modular code once and deploy it any way you need - bundled together as a monolith or distributed as microservices. We've been using it as the foundation for many of our products, from SAP integrations to open source projects like eryph.
How Hosuto Works
Hosuto enables you to build modules instead of monoliths or microservices. These modules can run together in one process or distributed across multiple services. The module code remains identical regardless of deployment configuration.
The architecture centers around a parent host (ModulesHost) that coordinates multiple modules. Each module runs within its own isolated host context (IModuleHost<T>
) with its own dependency injection container, while still having access to shared services from the parent host's DI container. This design provides module isolation while enabling resource sharing - modules can't interfere with each other's services, but they can access common infrastructure like configuration, logging, and message buses.
Option 1: Bundled
Option 2: Distributed
Module Structure
A module is a C# class that defines its services and configuration:
public class OrderModule : IWebModule
{
public string Path => "/orders";
public void ConfigureServices(IServiceProvider serviceProvider, IServiceCollection services)
{
// Inject shared services from the host
services.AddSingleton(serviceProvider.GetRequiredService<IEventBus>());
// Configure module-specific services
services.AddScoped<IOrderService, OrderService>();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
Bundled Deployment
For development or simple deployments, run all modules in one process:
// Program.cs - Everything in one process
public static IHostBuilder CreateHostBuilder(string[] args)
{
var services = new ServiceCollection()
.AddSingleton<IEventBus, InMemoryEventBus>()
.AddSingleton<IOrderRepository, OrderRepository>();
return ModulesHost.CreateDefaultBuilder(args)
.UseServiceCollection(services)
.UseAspNetCoreWithDefaults()
.HostModule<OrderModule>() // Orders API
.HostModule<PaymentModule>() // Payments API
.HostModule<InventoryModule>() // Inventory API
.HostModule<UIModule>() // Web UI
.ConfigureAppConfiguration(config => config
.AddInMemoryCollection(new Dictionary<string, string>
{
["bus:type"] = "inmemory", // In-process communication
["databus:type"] = "inmemory"
}));
}
Distributed Deployment
To scale individual components, extract modules to separate services without modifying module code:
// OrderService/Program.cs - Just the Order module now
public static IHostBuilder CreateHostBuilder(string[] args)
{
var services = new ServiceCollection()
.AddRabbitMqEventBus() // Distributed event bus
.AddCosmosDbRepository(); // Shared database
return ModulesHost.CreateDefaultBuilder(args)
.UseServiceCollection(services)
.UseAspNetCoreWithDefaults()
.HostModule<OrderModule>() // Only the Order module
.ConfigureAppConfiguration(config => config
.AddEnvironmentVariables("MYAPP_")
.AddInMemoryCollection(new Dictionary<string, string>
{
["bus:type"] = "rabbitmq",
["bus:connectionstring"] = "amqp://guest:guest@rabbitmq"
}));
}
Production Example: SAPHub
SAPHub demonstrates Hosuto in a production environment.
SAPHub provides a REST API for asynchronous SAP data access, built with three modules:
- API Module: REST endpoints for external clients
- UI Module: Blazor-based management interface
- SAP Connector Module: Handles SAP system integration
Module communication is determined by configuration:
Development (In-Memory):
{
"bus": { "type": "inmemory" },
"databus": { "type": "inmemory" }
}
Production (Distributed):
{
"bus": {
"type": "rabbitmq",
"connectionstring": "amqp://guest:guest@rabbitmq"
},
"databus": {
"type": "azurestorage",
"connectionstring": "DefaultEndpointsProtocol=https;..."
}
}
Different Ways to Deploy
Everything together:
// SAPHub.Server - Everything in one process
.HostModule<ApiModule>()
.HostModule<UIModule>()
.HostModule<SAPConnectorModule>()
API-Only Service:
// SAPHub.ApiEndpoint - Just the API
.HostModule<ApiModule>()
Connector-Only Service:
// SAPHub.SAPConnector - Just the SAP integration
.HostModule<SAPConnectorModule>()
Benefits
Hosuto provides deployment flexibility. The same module code can be deployed bundled together in a single process or distributed across multiple services, depending on your requirements.
Want to Try It?
Here's how to get started:
Install the package:
dotnet add package Dbosoft.Hosuto
Create a module:
public class MyModule : IWebModule
{
public string Path => "/api";
public void ConfigureServices(IServiceProvider serviceProvider, IServiceCollection services)
{
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints => endpoints.MapControllers());
}
}
Host it:
ModulesHost.CreateDefaultBuilder(args)
.UseAspNetCoreWithDefaults()
.HostModule<MyModule>()
.Build()
.Run();
When scaling requirements emerge, extract modules to separate services without code modifications.
Conclusion
Hosuto addresses the deployment flexibility challenge in enterprise software. Rather than committing to monolithic or microservices architecture upfront, teams can start with bundled deployment and transition to distributed services as requirements evolve.
Module code remains constant across deployment configurations, enabling architectural evolution without rewrites. This approach reduces both initial complexity and long-term technical debt.
Want to see Hosuto in action? Check out the SAPHub sample application or explore the Hosuto documentation to get started with your own flexible .NET applications.
Top comments (0)