Member-only story
Hexagonal Architecture in .NET C#: From layers to Ports and Adapters (2026)
Imagine your e-commerce has survived its second year. The order feature lives in a tidy layered solution, and then three requests arrive in the same week: the payment provider is retiring its old API, a marketplace wants its orders imported every night from a file, and the QA team wants to run the whole order flow on a laptop, with no database server and no real card. (If you want to find out more about the layered solution of the order feature, click here.)
You open the use case and the problem is clear. Even in a good layered solution the rules sit on top of the data layer, and when they reach for the database, the payment provider and the mail server themselves, they look like this:
// Naive approach - What NOT to do
// Shop.Business references EF Core, System.Net.Mail and knows where the payment provider lives
public sealed class OrderService(ShopDbContext db, IConfiguration configuration)
{
public async Task<bool> PlaceOrderAsync(PlaceOrderCommand command, CancellationToken cancellationToken)
{
var order = Order.Draft(command.CustomerId, DateTimeOffset.UtcNow);
// ... stock, lines and coupon rules ...
using var payments = new HttpClient { BaseAddress = new Uri(configuration["Payments:BaseAddress"]!) };
using var charge = await payments.PostAsJsonAsync("/charges", new { command.CustomerId, Amount = order.Total.Amount }, cancellationToken);
if (!charge.IsSuccessStatusCode)
return false…









