| Service Per Subdomain Pattern :👈 | 👉:Asynchronous Messaging Pattern |
Service Per Business Capability Pattern |
Service Per Business Capability Pattern in Microservices
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:
- Customer Management
- Order Processing
- Billing
- Inventory Management
- Shipping
- Human Resources
- Payroll
Each capability becomes an independent microservice.
What is a Business Capability?
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:
- Business Rules
- Database
- APIs
- UI Components (optional)
- Independent Team
Therefore:
Customer Management -> Customer Service
Order Processing -> Order Service
Payments -> Payment Service
Inventory -> Inventory Service
Shipping -> Shipping Service
Core Principle
Instead of dividing services by technical layers:
❌ Wrong Approach
User API Service
Database Service
Validation Service
Logging Service
Email Service
This creates excessive service communication.
Instead, divide by business responsibility.
✅ Correct Approach
Customer Service
Order Service
Payment Service
Inventory Service
Each service contains everything needed for its business capability.
Real World Example: Amazon-like Application
Imagine an e-commerce system.
Monolithic System
ECommerce Application
├── Customer Module
├── Product Module
├── Cart Module
├── Orders Module
├── Payments Module
├── Inventory Module
└── Shipping Module
Everything is deployed together.
Problems:
- Huge codebase
- Difficult deployments
- Long testing cycles
- Hard scalability
Service Per Business Capability
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
Responsibility of Each Service
Customer Service
Handles:
- Registration
- Login
- Customer Profile
- Address Management
Endpoints:
GET /api/customers/1
POST /api/customers
PUT /api/customers/1
Database:
CustomerDB
Product Service
Handles:
- Product Catalog
- Categories
- Product Details
Endpoints:
GET /api/products
GET /api/products/100
Database:
ProductDB
Order Service
Handles:
- Create Order
- Cancel Order
- Track Order
Endpoints:
POST /api/orders
GET /api/orders/1001
Database:
OrderDB
Payment Service
Handles:
- Credit Card Payment
- Refund
- Transaction History
Endpoints:
POST /api/payments
Database:
PaymentDB
Order Placement Flow
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.
.NET Example
Let's create an Order Service responsible for the Order Processing capability.
Order Entity
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; }
}
DbContext
using Microsoft.EntityFrameworkCore;
public class OrderDbContext : DbContext
{
public OrderDbContext(DbContextOptions<OrderDbContext> options)
: base(options)
{
}
public DbSet<Order> Orders { get; set; }
}
Order Service Layer
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);
}
}
Orders Controller
[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);
}
}
Each Capability Has Its Own Database
One major principle:
✅ Recommended
Customer Service --> CustomerDB
Order Service --> OrderDB
Payment Service --> PaymentDB
❌ Not Recommended
Customer Service
Order Service
Payment Service
│
▼
SharedDB
A shared database creates tight coupling between services.
Communication Between Business Capabilities
Synchronous Communication
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}");
}
}
Asynchronous Communication
Using:
- RabbitMQ
- Azure Service Bus
- Kafka
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
}
}
Service Per Business Capability vs Service Per Subdomain
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 |
Example
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.
Advantages
1. Independent Development
Team A → Orders
Team B → Payments
Team C → Inventory
Teams work independently.
2. Independent Deployment
Deploy Payment Service without redeploying Order Service.
3. Independent Scaling
If orders increase:
Order Service = 20 Pods
Payment Service = 5 Pods
Only the busy service scales.
4. Fault Isolation
If Shipping Service crashes:
Shipping = Down
Orders = Working
Products = Working
Customers = Working
The whole application does not fail.
5. Technology Flexibility
Order Service -> .NET
Payment Service -> Java
Search Service -> Node.js
Each capability can choose the best technology.
Challenges
Distributed Transactions
Example:
Order Created
Inventory Updated
Payment Failed
You need patterns like:
- Saga Pattern
- Event Sourcing
- Compensation Transactions
Network Latency
Services communicate over the network instead of method calls.
Monitoring Complexity
Need tools such as:
- OpenTelemetry
- Application Insights
- Grafana
- ELK Stack
Interview Definition
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 |
Comments and Discussion