IConfiguration vs IOptions NET
Synchronous and Asynchronous in .NET Core
Model Binding and Validation in ASP.NET Core
ControllerBase vs Controller in ASP.NET Core
ConfigureServices and Configure methods
IHostedService interface in .NET Core
ASP.NET Core request processing
| Service Per Subdomain Pattern :👈 | 👉:Asynchronous Messaging Pattern |
Service Per Business Capability Pattern |
The Service Per Business Capability pattern is one of the most common ways to design microservices. The idea is simple:
Each microservice is responsible for one complete business capability of the organization.
A business capability is something a business does to deliver value.
Examples:
Each capability becomes an independent microservice.
A business capability represents a specific business function that can operate relatively independently.
For example, in an online shopping company:
Business Capabilities ├── Customer Management ├── Product Catalog ├── Shopping Cart ├── Order Processing ├── Payment Processing ├── Inventory Management ├── Shipping └── Notification
Each capability has:
Therefore:
Customer Management -> Customer Service Order Processing -> Order Service Payments -> Payment Service Inventory -> Inventory Service Shipping -> Shipping Service
Instead of dividing services by technical layers:
User API Service Database Service Validation Service Logging Service Email Service
This creates excessive service communication.
Instead, divide by business responsibility.
Customer Service Order Service Payment Service Inventory Service
Each service contains everything needed for its business capability.
Imagine an e-commerce system.
ECommerce Application ├── Customer Module ├── Product Module ├── Cart Module ├── Orders Module ├── Payments Module ├── Inventory Module └── Shipping Module
Everything is deployed together.
Problems:
The monolith is split into independent services.
API Gateway
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
Customer Service Order Service Product Service
▼ ▼ ▼
CustomerDB OrderDB ProductDB
│
┌──────────┼──────────┐
▼ ▼ ▼
Inventory Service Payment Service Shipping Service
▼ ▼ ▼
InventoryDB PaymentDB ShippingDB
Handles:
Endpoints:
GET /api/customers/1 POST /api/customers PUT /api/customers/1
Database:
CustomerDB
Handles:
Endpoints:
GET /api/products GET /api/products/100
Database:
ProductDB
Handles:
Endpoints:
POST /api/orders GET /api/orders/1001
Database:
OrderDB
Handles:
Endpoints:
POST /api/payments
Database:
PaymentDB
When a customer places an order:
Customer │ ▼ Order Service │ ├── Get Product Details │ ▼ Product Service │ ▼ Inventory Service │ ▼ Payment Service │ ▼ Shipping Service
Every service contributes only to its own capability.
Let's create an Order Service responsible for the Order Processing capability.
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
public decimal Amount { get; set; }
public string Status { get; set; }
public DateTime CreatedDate { get; set; }
}
using Microsoft.EntityFrameworkCore;
public class OrderDbContext : DbContext
{
public OrderDbContext(DbContextOptions<OrderDbContext> options)
: base(options)
{
}
public DbSet<Order> Orders { get; set; }
}
public class OrderService
{
private readonly OrderDbContext _context;
public OrderService(OrderDbContext context)
{
_context = context;
}
public async Task<Order> CreateOrderAsync(Order order)
{
_context.Orders.Add(order);
await _context.SaveChangesAsync();
return order;
}
public async Task<Order?> GetOrderAsync(int id)
{
return await _context.Orders.FindAsync(id);
}
}
[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
private readonly OrderService _service;
public OrdersController(OrderService service)
{
_service = service;
}
[HttpPost]
public async Task<IActionResult> Create(Order order)
{
var result =
await _service.CreateOrderAsync(order);
return Ok(result);
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
var order =
await _service.GetOrderAsync(id);
if (order == null)
return NotFound();
return Ok(order);
}
}
One major principle:
Customer Service --> CustomerDB Order Service --> OrderDB Payment Service --> PaymentDB
Customer Service
Order Service
Payment Service
│
▼
SharedDB
A shared database creates tight coupling between services.
Using REST APIs.
Order Service calls Customer Service.
public class CustomerClient
{
private readonly HttpClient _httpClient;
public CustomerClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<CustomerDto> GetCustomer(int id)
{
return await _httpClient
.GetFromJsonAsync<CustomerDto>
($"api/customers/{id}");
}
}
Using:
Order Service publishes:
public class OrderCreatedEvent
{
public int OrderId { get; set; }
public decimal Amount { get; set; }
}
Publish:
await _publishEndpoint.Publish(
new OrderCreatedEvent
{
OrderId = 100,
Amount = 5000
});
Payment Service consumes:
public class OrderCreatedConsumer :
IConsumer<OrderCreatedEvent>
{
public async Task Consume(
ConsumeContext<OrderCreatedEvent> context)
{
var order = context.Message;
// Process Payment
}
}
Many developers think they are the same, but there is a small difference.
| Service Per Business Capability | Service Per Subdomain |
|---|---|
| Based on business functions | Based on Domain-Driven Design subdomains |
| Simpler approach | DDD-oriented approach |
| Focus on what business does | Focus on bounded contexts |
| Good starting point | Better for large enterprise systems |
Business Capability View:
Customer Management Orders Payments Shipping
DDD Subdomain View:
Customer Domain ├── Customer Profile ├── Loyalty Program └── Customer Preferences
A large subdomain may eventually contain multiple business capabilities.
Team A → Orders Team B → Payments Team C → Inventory
Teams work independently.
Deploy Payment Service without redeploying Order Service.
If orders increase:
Order Service = 20 Pods Payment Service = 5 Pods
Only the busy service scales.
If Shipping Service crashes:
Shipping = Down Orders = Working Products = Working Customers = Working
The whole application does not fail.
Order Service -> .NET Payment Service -> Java Search Service -> Node.js
Each capability can choose the best technology.
Example:
Order Created Inventory Updated Payment Failed
You need patterns like:
Services communicate over the network instead of method calls.
Need tools such as:
Service Per Business Capability Pattern is a microservice design pattern where each microservice is organized around a single business capability, such as Orders, Payments, Inventory, or Customers. Each service owns its business logic, database, APIs, and deployment lifecycle, enabling independent development, deployment, and scaling while maintaining clear business boundaries.
| Service Per Subdomain Pattern :👈 | 👉:Asynchronous Messaging Pattern |