Claude Code Plugins

Community-maintained marketplace

Feedback

microservices-architecture

@aj-geddes/useful-ai-prompts
4
0

Design and implement microservices architecture including service boundaries, communication patterns, API gateways, service mesh, service discovery, and distributed system patterns. Use when building microservices, distributed systems, or service-oriented architectures.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name microservices-architecture
description Design and implement microservices architecture including service boundaries, communication patterns, API gateways, service mesh, service discovery, and distributed system patterns. Use when building microservices, distributed systems, or service-oriented architectures.

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:

  1. By Business Capability
E-commerce System:
- Product Catalog Service
- Shopping Cart Service
- Order Management Service
- Payment Service
- Inventory Service
- Shipping Service
- User Account Service
  1. 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