
Microservices Architecture
- 471 installs
- 305 repo stars
- Updated March 4, 2026
- aj-geddes/useful-ai-prompts
microservices-architecture is a Claude skill that guides developers through decomposing monoliths into bounded services with APIs, messaging, gateways, service mesh, and observability for distributed SaaS backends.
About
microservices-architecture is an aj-geddes/useful-ai-prompts skill for designing and implementing microservices and service-oriented architectures. It walks through bounded contexts such as Order, User, and Payment services, asynchronous communication, circuit breakers, API gateways, service discovery, database-per-service data consistency, and Istio service mesh patterns. Six reference guides cover service boundary design, communication patterns, API gateway pattern, service discovery, data consistency patterns, and service mesh with Istio, plus explicit do-and-don't lists for idempotency, correlation IDs, and chaos-ready health checks. Developers reach for microservices-architecture when splitting monoliths, defining inter-service contracts, or planning observability and failure handling for independent deployable services.
- Domain-driven service boundaries
- Sync vs async communication patterns
- Data ownership and schema strategy
- API versioning and contracts
- Observability and failure isolation
Microservices Architecture by the numbers
- 471 all-time installs (skills.sh)
- Ranked #866 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill microservices-architectureAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 471 |
|---|---|
| repo stars | ★ 305 |
| Last updated | March 4, 2026 |
| Repository | aj-geddes/useful-ai-prompts ↗ |
How do you decompose a monolith into microservices?
Split monoliths into bounded services with clear APIs, data ownership, messaging, and observability for scalable SaaS backends.
Who is it for?
Backend engineers architecting distributed SaaS systems who need bounded contexts, gateway, mesh, and data-ownership guidance with reference deep dives.
Skip if: Single-process monoliths, frontend-only work, or teams that want copy-paste Terraform without service-boundary design decisions.
When should I use this skill?
Designing microservices, decomposing monoliths, planning API gateways, service mesh, or distributed transaction alternatives.
What you get
Bounded service diagrams, API gateway plans, communication pattern choices, data consistency strategies, and Istio mesh reference notes.
- Service boundary diagrams
- Architecture decision notes
- Reference guide implementations
By the numbers
- Includes 6 reference guides for microservices architecture topics
Files
Microservices Architecture
Table of Contents
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
Quick Start
Minimal working example:
Bounded Contexts:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Order Service │ │ User Service │ │ Payment Service │
│ │ │ │ │ │
│ - Create Order │ │ - User Profile │ │ - Process Pay │
│ - Order Status │ │ - Auth │ │ - Refund │
│ - Order History │ │ - Preferences │ │ - Transactions │
└─────────────────┘ └─────────────────┘ └─────────────────┘Reference Guides
Detailed implementations in the references/ directory:
| Guide | Contents |
|---|---|
| Service Boundary Design | Service Boundary Design |
| Communication Patterns | Communication Patterns |
| API Gateway Pattern | API Gateway Pattern |
| Service Discovery | Service Discovery |
| Data Consistency Patterns | Data Consistency Patterns |
| Service Mesh (Istio) | Service Mesh (Istio) |
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
API Gateway Pattern
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 });
});Communication Patterns
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);
},
});Data Consistency Patterns
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;
}
}Service Boundary Design
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 Service2. 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;
}
}Service Discovery
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}`);Service Mesh (Istio)
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#!/bin/bash
# validate-config.sh - Validate infrastructure configuration
# Usage: ./validate-config.sh <config_file>
set -euo pipefail
CONFIG_FILE="${{1:?Usage: $0 <config_file>}}"
echo "Validating: $CONFIG_FILE"
# TODO: Add configuration validation logic
# - Check required fields
# - Validate syntax (YAML/JSON/HCL)
# - Verify referenced resources exist
# - Check for security best practices
echo "Validation complete."
# Infrastructure Configuration Starter
# TODO: Customize for your infrastructure setup
#
# Usage: Copy this file and modify for your environment
# --- Environment Configuration ---
environment: production
region: us-east-1
# --- Resource Definitions ---
# TODO: Add resource definitions specific to this skill's domain
# --- Security Settings ---
# TODO: Add security configuration
# --- Monitoring ---
# TODO: Add monitoring/alerting configuration
Related skills
How it compares
Use microservices-architecture for distributed backend decomposition patterns rather than single-service NestJS or Express implementation skills.
FAQ
What topics does microservices-architecture cover?
microservices-architecture covers service boundary design, communication patterns, API gateways, service discovery, data consistency, and Istio service mesh. Reference guides in references/ expand each area with implementation patterns.
What practices does microservices-architecture discourage?
microservices-architecture discourages shared databases between services, nanoservices, distributed two-phase commit, hardcoded service URLs, and deploying all services as one unit without health checks or correlation IDs.