microservices-architecture
About
This skill provides comprehensive guidance for designing and implementing microservices architectures, including service boundaries, communication patterns, and distributed system components. Use it when building microservices, decomposing monoliths, or implementing service discovery and API gateways. It covers essential patterns for service-to-service communication, data consistency, and scaling independent services.
Documentation
Microservices Architecture
Overview
Comprehensive guide to designing, implementing, and maintaining microservices architectures. Covers service decomposition, communication patterns, data management, deployment strategies, and observability for distributed systems.
When to Use
- Designing new microservices architectures
- Decomposing monolithic applications
- Implementing service-to-service communication
- Setting up API gateways and service mesh
- Implementing service discovery
- Managing distributed transactions
- Designing inter-service data consistency
- Scaling independent services
Instructions
1. Service Boundary Design
Domain-Driven Design (DDD) Approach
Bounded Contexts:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Order Service │ │ User Service │ │ Payment Service │
│ │ │ │ │ │
│ - Create Order │ │ - User Profile │ │ - Process Pay │
│ - Order Status │ │ - Auth │ │ - Refund │
│ - Order History │ │ - Preferences │ │ - Transactions │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Decomposition Strategies:
- By Business Capability
E-commerce System:
- Product Catalog Service
- Shopping Cart Service
- Order Management Service
- Payment Service
- Inventory Service
- Shipping Service
- User Account Service
- By Subdomain
Healthcare System:
- Patient Management (Core Domain)
- Appointment Scheduling (Core Domain)
- Billing (Supporting Domain)
- Notifications (Generic Domain)
- Reporting (Generic Domain)
Service Design Example
// order-service/src/domain/order.ts
export class OrderService {
constructor(
private orderRepository: OrderRepository,
private eventBus: EventBus,
private paymentClient: PaymentClient,
private inventoryClient: InventoryClient
) {}
async createOrder(request: CreateOrderRequest): Promise<Order> {
// 1. Validate order
const order = Order.create(request);
// 2. Check inventory (synchronous call)
const available = await this.inventoryClient.checkAvailability(
order.items
);
if (!available) {
throw new InsufficientInventoryError();
}
// 3. Save order
await this.orderRepository.save(order);
// 4. Publish event (asynchronous)
await this.eventBus.publish(new OrderCreatedEvent(order));
return order;
}
}
2. Communication Patterns
Synchronous Communication (REST/gRPC)
REST API Example:
// user-service/src/api/user.controller.ts
import express from 'express';
const router = express.Router();
// Get user profile
router.get('/users/:id', async (req, res) => {
try {
const user = await userService.findById(req.params.id);
res.json(user);
} catch (error) {
if (error instanceof UserNotFoundError) {
res.status(404).json({ error: 'User not found' });
} else {
res.status(500).json({ error: 'Internal server error' });
}
}
});
// Service-to-service call with circuit breaker
import axios from 'axios';
import CircuitBreaker from 'opossum';
const options = {
timeout: 3000,
errorThresholdPercentage: 50,
resetTimeout: 30000
};
const breaker = new CircuitBreaker(
async (userId: string) => {
const response = await axios.get(
`http://user-service/users/${userId}`,
{ timeout: 2000 }
);
return response.data;
},
options
);
breaker.fallback(() => ({ id: userId, name: 'Unknown User' }));
gRPC Example:
// proto/user.proto
syntax = "proto3";
package user;
service UserService {
rpc GetUser (GetUserRequest) returns (UserResponse);
rpc ListUsers (ListUsersRequest) returns (stream UserResponse);
}
message GetUserRequest {
string user_id = 1;
}
message UserResponse {
string user_id = 1;
string email = 2;
string name = 3;
}
// Implementation
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
const packageDefinition = protoLoader.loadSync('proto/user.proto');
const userProto = grpc.loadPackageDefinition(packageDefinition).user;
// Server
function getUser(call, callback) {
const userId = call.request.user_id;
const user = await userService.findById(userId);
callback(null, user);
}
const server = new grpc.Server();
server.addService(userProto.UserService.service, { getUser });
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
Asynchronous Communication (Message Queue)
Event-Driven with RabbitMQ:
// order-service/src/events/publisher.ts
import amqp from 'amqplib';
export class EventPublisher {
private connection: amqp.Connection;
private channel: amqp.Channel;
async connect() {
this.connection = await amqp.connect('amqp://localhost');
this.channel = await this.connection.createChannel();
await this.channel.assertExchange('orders', 'topic', { durable: true });
}
async publishOrderCreated(order: Order) {
const event = {
eventType: 'OrderCreated',
timestamp: new Date(),
data: order
};
this.channel.publish(
'orders',
'order.created',
Buffer.from(JSON.stringify(event)),
{ persistent: true }
);
}
}
// inventory-service/src/events/consumer.ts
export class OrderEventConsumer {
async subscribe() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
await channel.assertExchange('orders', 'topic', { durable: true });
const q = await channel.assertQueue('inventory-order-events', {
durable: true
});
await channel.bindQueue(q.queue, 'orders', 'order.created');
channel.consume(q.queue, async (msg) => {
if (msg) {
const event = JSON.parse(msg.content.toString());
await this.handleOrderCreated(event.data);
channel.ack(msg);
}
});
}
private async handleOrderCreated(order: Order) {
// Reserve inventory
await inventoryService.reserveItems(order.items);
}
}
Kafka Event Streaming:
// event-streaming/kafka-producer.ts
import { Kafka } from 'kafkajs';
const kafka = new Kafka({
clientId: 'order-service',
brokers: ['kafka:9092']
});
const producer = kafka.producer();
export async function publishEvent(topic: string, event: any) {
await producer.connect();
await producer.send({
topic,
messages: [
{
key: event.aggregateId,
value: JSON.stringify(event),
headers: {
'event-type': event.type,
'correlation-id': event.correlationId
}
}
]
});
}
// Consumer
const consumer = kafka.consumer({ groupId: 'inventory-service' });
await consumer.subscribe({ topic: 'order-events', fromBeginning: false });
await consumer.run({
eachMessage: async ({ topic, partition, message }) => {
const event = JSON.parse(message.value.toString());
await eventHandler.handle(event);
}
});
3. API Gateway Pattern
// api-gateway/src/gateway.ts
import express from 'express';
import httpProxy from 'http-proxy-middleware';
import jwt from 'jsonwebtoken';
import rateLimit from 'express-rate-limit';
const app = express();
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100
});
app.use(limiter);
// Authentication middleware
const authenticateToken = (req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
// Route to services
app.use('/api/users', authenticateToken, httpProxy.createProxyMiddleware({
target: 'http://user-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/users': '/users' }
}));
app.use('/api/orders', authenticateToken, httpProxy.createProxyMiddleware({
target: 'http://order-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/orders': '/orders' }
}));
app.use('/api/products', httpProxy.createProxyMiddleware({
target: 'http://product-service:3000',
changeOrigin: true,
pathRewrite: { '^/api/products': '/products' }
}));
// Aggregation endpoint
app.get('/api/order-details/:orderId', authenticateToken, async (req, res) => {
const orderId = req.params.orderId;
// Parallel requests to multiple services
const [order, user, products] = await Promise.all([
fetch(`http://order-service:3000/orders/${orderId}`).then(r => r.json()),
fetch(`http://user-service:3000/users/${req.user.id}`).then(r => r.json()),
fetch(`http://product-service:3000/products?ids=${order.itemIds}`).then(r => r.json())
]);
res.json({ order, user, products });
});
4. Service Discovery
Consul Example
// service-registry/consul-client.ts
import Consul from 'consul';
export class ServiceRegistry {
private consul: Consul.Consul;
constructor() {
this.consul = new Consul({
host: 'consul',
port: 8500
});
}
// Register service
async register(serviceName: string, servicePort: number) {
await this.consul.agent.service.register({
id: `${serviceName}-${process.env.HOSTNAME}`,
name: serviceName,
address: process.env.SERVICE_IP,
port: servicePort,
check: {
http: `http://${process.env.SERVICE_IP}:${servicePort}/health`,
interval: '10s',
timeout: '5s'
}
});
}
// Discover service
async discover(serviceName: string): Promise<string> {
const result = await this.consul.health.service({
service: serviceName,
passing: true
});
if (result.length === 0) {
throw new Error(`Service ${serviceName} not found`);
}
// Simple round-robin
const service = result[Math.floor(Math.random() * result.length)];
return `http://${service.Service.Address}:${service.Service.Port}`;
}
// Deregister on shutdown
async deregister(serviceId: string) {
await this.consul.agent.service.deregister(serviceId);
}
}
Kubernetes Service Discovery
# user-service-deployment.yaml
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 3000
env:
- name: SERVICE_NAME
value: "user-service"
// Service call in Kubernetes
const userServiceUrl = process.env.USER_SERVICE_URL || 'http://user-service';
const response = await fetch(`${userServiceUrl}/users/${userId}`);
5. Data Consistency Patterns
Saga Pattern (Orchestration)
// order-saga-orchestrator.ts
export class OrderSagaOrchestrator {
async createOrder(orderData: CreateOrderRequest) {
const sagaId = uuidv4();
const saga = new SagaInstance(sagaId);
try {
// Step 1: Create order
const order = await this.orderService.createOrder(orderData);
saga.addCompensation(() => this.orderService.cancelOrder(order.id));
// Step 2: Reserve inventory
await this.inventoryService.reserveItems(order.items);
saga.addCompensation(() =>
this.inventoryService.releaseReservation(order.id)
);
// Step 3: Process payment
const payment = await this.paymentService.charge(order.total);
saga.addCompensation(() =>
this.paymentService.refund(payment.id)
);
// Step 4: Confirm order
await this.orderService.confirmOrder(order.id);
return order;
} catch (error) {
// Compensate in reverse order
await saga.compensate();
throw error;
}
}
}
Event Sourcing Pattern
// order-aggregate.ts
export class OrderAggregate {
private id: string;
private status: OrderStatus;
private items: OrderItem[];
private events: DomainEvent[] = [];
// Command handler
createOrder(command: CreateOrderCommand) {
// Validation
if (this.id) throw new Error('Order already exists');
// Apply event
this.apply(new OrderCreatedEvent({
orderId: command.orderId,
userId: command.userId,
items: command.items
}));
}
// Event handler
private apply(event: DomainEvent) {
switch (event.type) {
case 'OrderCreated':
this.id = event.orderId;
this.items = event.items;
this.status = OrderStatus.PENDING;
break;
case 'OrderConfirmed':
this.status = OrderStatus.CONFIRMED;
break;
}
this.events.push(event);
}
getUncommittedEvents(): DomainEvent[] {
return this.events;
}
}
6. Service Mesh (Istio)
# istio-config.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: order-service
spec:
hosts:
- order-service
http:
- match:
- headers:
user-type:
exact: premium
route:
- destination:
host: order-service
subset: v2
weight: 100
- route:
- destination:
host: order-service
subset: v1
weight: 90
- destination:
host: order-service
subset: v2
weight: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: order-service
spec:
host: order-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 2
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Best Practices
✅ DO
- Design services around business capabilities
- Use asynchronous communication where possible
- Implement circuit breakers for resilience
- Use API gateway for cross-cutting concerns
- Implement distributed tracing
- Use service mesh for service-to-service communication
- Design for failure (chaos engineering)
- Implement health checks for all services
- Use correlation IDs for request tracking
- Version your APIs
- Implement proper monitoring and alerting
- Use event-driven architecture for loose coupling
- Implement idempotent operations
- Use database per service pattern
❌ DON'T
- Share databases between services
- Create overly granular services (nanoservices)
- Use distributed transactions (two-phase commit)
- Ignore network latency and failures
- Share domain models between services
- Deploy all services as one unit
- Hardcode service URLs
- Forget to implement authentication/authorization
- Use synchronous calls for long-running operations
- Ignore backward compatibility
- Skip monitoring and logging
- Create circular dependencies between services
Common Patterns
Pattern 1: Backend for Frontend (BFF)
// mobile-bff/src/api.ts - Optimized for mobile
app.get('/api/home', async (req, res) => {
const [featured, recommendations] = await Promise.all([
productService.getFeatured(5),
recommendationService.getForUser(req.user.id, 10)
]);
res.json({ featured, recommendations });
});
// web-bff/src/api.ts - More data for web
app.get('/api/home', async (req, res) => {
const [featured, recommendations, categories, promotions] = await Promise.all([
productService.getFeatured(20),
recommendationService.getForUser(req.user.id, 50),
categoryService.getAll(),
promotionService.getActive()
]);
res.json({ featured, recommendations, categories, promotions });
});
Pattern 2: Sidecar Pattern
# Pod with sidecar
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
- name: app
image: my-app:latest
- name: logging-sidecar
image: fluentd:latest
volumeMounts:
- name: logs
mountPath: /logs
volumes:
- name: logs
emptyDir: {}
Tools & Resources
- Service Mesh: Istio, Linkerd, Consul Connect
- API Gateway: Kong, Apigee, AWS API Gateway
- Service Discovery: Consul, Eureka, Zookeeper
- Message Queue: RabbitMQ, Apache Kafka, AWS SQS
- Orchestration: Kubernetes, Docker Swarm, Nomad
- Monitoring: Prometheus, Grafana, Datadog
- Tracing: Jaeger, Zipkin, AWS X-Ray
- Circuit Breaker: Hystrix, Resilience4j, Polly
Quick Install
/plugin add https://github.com/aj-geddes/useful-ai-prompts/tree/main/microservices-architectureCopy and paste this command in Claude Code to install this skill
GitHub 仓库
Related Skills
evaluating-llms-harness
TestingThis Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.
langchain
MetaLangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.
Algorithmic Art Generation
MetaThis skill helps developers create algorithmic art using p5.js, focusing on generative art, computational aesthetics, and interactive visualizations. It automatically activates for topics like "generative art" or "p5.js visualization" and guides you through creating unique algorithms with features like seeded randomness, flow fields, and particle systems. Use it when you need to build reproducible, code-driven artistic patterns.
webapp-testing
TestingThis Claude Skill provides a Playwright-based toolkit for testing local web applications through Python scripts. It enables frontend verification, UI debugging, screenshot capture, and log viewing while managing server lifecycles. Use it for browser automation tasks but run scripts directly rather than reading their source code to avoid context pollution.
