Overview
Microservices architecture breaks applications into independent, scalable services. Learn patterns for design, communication, and deployment.
Key Patterns
- API Gateway: Single entry point for all services
- Service Discovery: Dynamic service location
- Event-Driven: Async communication between services
- Circuit Breaker: Handle failures gracefully
- Saga Pattern: Distributed transactions
Service Structure
services/
├── auth-service/
│ └── src/
│ ├── routes.ts
│ ├── controllers/
│ └── models/
├── user-service/
├── product-service/
└── order-service/
API Gateway Pattern
// gateway.ts
import express from 'express'
import { createProxyMiddleware } from 'express-http-proxy'
const app = express()
// Route to services
app.use('/auth', createProxyMiddleware({
target: 'http://auth-service:3001'
}))
app.use('/users', createProxyMiddleware({
target: 'http://user-service:3002'
}))
app.use('/products', createProxyMiddleware({
target: 'http://product-service:3003'
}))
Event-Driven Communication
import amqp from 'amqplib'
// Publish event
async function publishEvent(channel: any, event: string, data: any) {
const exchange = 'events'
await channel.assertExchange(exchange, 'topic', { durable: true })
channel.publish(exchange, event, Buffer.from(JSON.stringify(data)))
}
// Subscribe to events
async function subscribeToEvent(channel: any, event: string, handler: Function) {
const exchange = 'events'
const queue = await channel.assertQueue('', { exclusive: true })
await channel.bindQueue(queue.queue, exchange, event)
channel.consume(queue.queue, (msg) => {
if (msg) {
handler(JSON.parse(msg.content.toString()))
channel.ack(msg)
}
})
}
Circuit Breaker Pattern
class CircuitBreaker {
private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED'
private failureCount = 0
private threshold = 5
async call(fn: () => Promise<any>) {
if (this.state === 'OPEN') {
throw new Error('Circuit breaker is open')
}
try {
const result = await fn()
this.failureCount = 0
this.state = 'CLOSED'
return result
} catch (error) {
this.failureCount++
if (this.failureCount >= this.threshold) {
this.state = 'OPEN'
setTimeout(() => this.state = 'HALF_OPEN', 30000)
}
throw error
}
}
}
Microservices enable teams to deploy changes independently, reducing time-to-market by 50%.