Skip to content

Workshop: Microservices Architecture (5 hours) ​

Build a complete microservices system with service discovery, API gateway, distributed data management, and orchestrated deployment. Create an e-commerce platform that demonstrates enterprise microservices patterns.

Workshop Overview ​

Duration: 5 hours Difficulty: Advanced Result: Production-ready microservices system

You'll build MicroMart - an e-commerce platform with:

  • πŸ—οΈ Multiple independent services
  • 🌐 API Gateway with authentication
  • πŸ“Š Event-driven architecture
  • πŸ”„ Service discovery & load balancing
  • πŸ“ˆ Distributed tracing & monitoring
  • πŸš€ Container orchestration
  • πŸ’Ύ Distributed data management

Prerequisites ​

  • Orchestre installed
  • Docker and Docker Compose
  • Basic microservices knowledge
  • 5 hours of focused time

Part 1: Architecture Design (45 minutes) ​

System Planning ​

bash
/orchestrate "Design a microservices e-commerce platform with:
- User service (authentication, profiles)
- Product catalog service  
- Inventory service
- Cart service
- Order service
- Payment service
- Notification service
- Search service

Requirements:
- Each service independently deployable
- Event-driven communication
- API gateway for external access
- Service mesh for internal communication
- Distributed data (each service owns its data)
- Fault tolerance and resilience"

Project Structure ​

bash
# Create the monorepo structure
mkdir micromart && cd micromart

# Initialize with service templates
/create services/user-service cloudflare-hono
/create services/product-service cloudflare-hono
/create services/order-service cloudflare-hono
/create services/payment-service cloudflare-hono
/create api-gateway cloudflare-hono

Architecture Overview ​

Part 2: Core Services (1 hour) ​

User Service ​

bash
cd services/user-service
/execute-task "Implement user service with JWT authentication and profile management"

Implementation:

typescript
// services/user-service/src/index.ts
import { Hono } from 'hono'
import { jwt } from 'hono/jwt'
import { EventBus } from '@micromart/event-bus'

const app = new Hono()
const eventBus = new EventBus()

// Health check for service discovery
app.get('/health', (c) => c.json({ status: 'healthy', service: 'user' }))

// User registration
app.post('/users/register', async (c) => {
  const { email, password, name } = await c.req.json()
  
  // Validate and hash password
  const hashedPassword = await hashPassword(password)
  
  // Create user
  const user = await db.users.create({
    id: generateId(),
    email,
    password: hashedPassword,
    name,
    createdAt: new Date()
  })
  
  // Emit event
  await eventBus.publish('user.created', {
    userId: user.id,
    email: user.email,
    timestamp: Date.now()
  })
  
  // Generate JWT
  const token = await generateJWT(user)
  
  return c.json({ user: sanitizeUser(user), token })
})

// User authentication
app.post('/users/login', async (c) => {
  const { email, password } = await c.req.json()
  
  const user = await db.users.findByEmail(email)
  if (!user || !await verifyPassword(password, user.password)) {
    return c.json({ error: 'Invalid credentials' }, 401)
  }
  
  const token = await generateJWT(user)
  
  // Emit login event
  await eventBus.publish('user.logged_in', {
    userId: user.id,
    timestamp: Date.now()
  })
  
  return c.json({ user: sanitizeUser(user), token })
})

// Protected routes
app.use('/users/*', jwt({ secret: process.env.JWT_SECRET }))

app.get('/users/profile', async (c) => {
  const userId = c.get('jwtPayload').userId
  const user = await db.users.findById(userId)
  return c.json(sanitizeUser(user))
})

export default app

Product Service ​

bash
cd ../product-service
/execute-task "Create product catalog service with search and filtering"

Product service implementation:

typescript
// services/product-service/src/index.ts
export const productService = new Hono()

// Product CRUD
productService.post('/products', authenticate('admin'), async (c) => {
  const product = await c.req.json()
  
  const created = await db.products.create({
    ...product,
    id: generateId(),
    createdAt: new Date()
  })
  
  // Update search index
  await searchClient.index('products').addDocuments([created])
  
  // Emit event
  await eventBus.publish('product.created', {
    productId: created.id,
    price: created.price,
    category: created.category
  })
  
  return c.json(created)
})

// Search with faceted filtering
productService.get('/products/search', async (c) => {
  const { 
    q = '',
    category,
    minPrice,
    maxPrice,
    inStock,
    page = 1,
    limit = 20 
  } = c.req.query()
  
  const searchParams = {
    query: q,
    filter: [],
    facets: ['category', 'brand', 'price_range'],
    page,
    hitsPerPage: limit
  }
  
  if (category) searchParams.filter.push(`category = "${category}"`)
  if (minPrice) searchParams.filter.push(`price >= ${minPrice}`)
  if (maxPrice) searchParams.filter.push(`price <= ${maxPrice}`)
  if (inStock) searchParams.filter.push('inventory > 0')
  
  const results = await searchClient
    .index('products')
    .search(q, searchParams)
  
  return c.json({
    products: results.hits,
    facets: results.facetDistribution,
    total: results.totalHits,
    page: results.page,
    totalPages: results.totalPages
  })
})

// Inventory check endpoint (for other services)
productService.post('/products/check-availability', async (c) => {
  const { items } = await c.req.json() // [{productId, quantity}]
  
  const availability = await Promise.all(
    items.map(async item => {
      const product = await db.products.findById(item.productId)
      return {
        productId: item.productId,
        available: product.inventory >= item.quantity,
        currentStock: product.inventory
      }
    })
  )
  
  return c.json(availability)
})

Order Service ​

bash
cd ../order-service
/execute-task "Implement order service with saga pattern for distributed transactions"

Order saga implementation:

typescript
// services/order-service/src/sagas/create-order.saga.ts
export class CreateOrderSaga {
  private steps = [
    { 
      name: 'validate-user',
      service: 'user-service',
      action: 'validateUser',
      compensate: null
    },
    {
      name: 'check-inventory',
      service: 'product-service', 
      action: 'checkInventory',
      compensate: null
    },
    {
      name: 'reserve-inventory',
      service: 'inventory-service',
      action: 'reserveItems',
      compensate: 'releaseItems'
    },
    {
      name: 'process-payment',
      service: 'payment-service',
      action: 'processPayment',
      compensate: 'refundPayment'
    },
    {
      name: 'create-order',
      service: 'order-service',
      action: 'createOrder',
      compensate: 'cancelOrder'
    },
    {
      name: 'update-inventory',
      service: 'inventory-service',
      action: 'confirmReservation',
      compensate: 'releaseItems'
    },
    {
      name: 'send-notification',
      service: 'notification-service',
      action: 'sendOrderConfirmation',
      compensate: null
    }
  ]
  
  async execute(orderData: CreateOrderRequest): Promise<Order> {
    const completedSteps: CompletedStep[] = []
    
    try {
      for (const step of this.steps) {
        const result = await this.executeStep(step, orderData)
        completedSteps.push({ step, result })
        
        // Pass results to next steps
        orderData = { ...orderData, ...result }
      }
      
      return orderData.order
    } catch (error) {
      // Compensate in reverse order
      await this.compensate(completedSteps.reverse())
      throw new SagaFailedError('Order creation failed', error)
    }
  }
  
  private async executeStep(step: SagaStep, data: any) {
    const service = this.serviceClient.get(step.service)
    return await service.call(step.action, data)
  }
  
  private async compensate(completedSteps: CompletedStep[]) {
    for (const { step, result } of completedSteps) {
      if (step.compensate) {
        try {
          const service = this.serviceClient.get(step.service)
          await service.call(step.compensate, result)
        } catch (error) {
          // Log compensation failure
          console.error(`Compensation failed for ${step.name}`, error)
        }
      }
    }
  }
}

Part 3: Infrastructure Services (1 hour) ​

API Gateway ​

bash
cd ../../api-gateway
/execute-task "Create API gateway with authentication, rate limiting, and request routing"

Gateway implementation:

typescript
// api-gateway/src/index.ts
import { Hono } from 'hono'
import { ServiceRegistry } from './service-registry'
import { RateLimiter } from './rate-limiter'
import { CircuitBreaker } from './circuit-breaker'

const gateway = new Hono()
const registry = new ServiceRegistry()
const rateLimiter = new RateLimiter()

// Middleware
gateway.use('*', async (c, next) => {
  // Rate limiting
  const ip = c.req.header('cf-connecting-ip')
  if (!await rateLimiter.checkLimit(ip)) {
    return c.json({ error: 'Rate limit exceeded' }, 429)
  }
  
  // Add tracing headers
  c.req.header('x-request-id', generateRequestId())
  c.req.header('x-trace-id', generateTraceId())
  
  await next()
})

// Service discovery and routing
gateway.all('/api/:service/*', async (c) => {
  const service = c.req.param('service')
  const path = c.req.path.replace(`/api/${service}`, '')
  
  // Get healthy service instance
  const instance = await registry.getHealthyInstance(service)
  if (!instance) {
    return c.json({ error: 'Service unavailable' }, 503)
  }
  
  // Circuit breaker
  const breaker = CircuitBreaker.for(service)
  
  try {
    const response = await breaker.call(async () => {
      return await fetch(`${instance.url}${path}`, {
        method: c.req.method,
        headers: {
          ...c.req.headers,
          'x-gateway-auth': process.env.INTERNAL_AUTH_KEY
        },
        body: c.req.body
      })
    })
    
    return new Response(response.body, {
      status: response.status,
      headers: response.headers
    })
  } catch (error) {
    return c.json({ 
      error: 'Service error',
      service,
      details: error.message 
    }, 503)
  }
})

// Health check endpoint
gateway.get('/health', async (c) => {
  const services = await registry.getAllServices()
  const health = await Promise.all(
    services.map(async service => ({
      name: service.name,
      status: await registry.checkHealth(service),
      instances: service.instances.length
    }))
  )
  
  return c.json({
    gateway: 'healthy',
    services: health
  })
})

export default gateway

Event Bus ​

bash
/execute-task "Implement event bus for asynchronous service communication"

Event bus implementation:

typescript
// shared/event-bus/src/index.ts
export class EventBus {
  private broker: KafkaClient
  private handlers: Map<string, EventHandler[]> = new Map()
  
  async publish(eventType: string, data: any) {
    const event = {
      id: generateId(),
      type: eventType,
      data,
      timestamp: Date.now(),
      source: process.env.SERVICE_NAME
    }
    
    await this.broker.send({
      topic: this.getTopicForEvent(eventType),
      messages: [{
        key: event.id,
        value: JSON.stringify(event),
        headers: {
          'event-type': eventType,
          'correlation-id': getCurrentCorrelationId()
        }
      }]
    })
    
    // Also emit locally for same-service handlers
    await this.emitLocal(event)
  }
  
  subscribe(eventPattern: string, handler: EventHandler) {
    const regex = new RegExp(eventPattern.replace('*', '.*'))
    
    if (!this.handlers.has(eventPattern)) {
      this.handlers.set(eventPattern, [])
      
      // Subscribe to Kafka topic
      this.broker.subscribe({
        topic: this.getTopicForPattern(eventPattern),
        fromBeginning: false
      })
    }
    
    this.handlers.get(eventPattern)!.push(handler)
  }
  
  private async handleMessage(message: KafkaMessage) {
    const event = JSON.parse(message.value.toString())
    
    for (const [pattern, handlers] of this.handlers) {
      if (new RegExp(pattern).test(event.type)) {
        await Promise.all(
          handlers.map(handler => 
            this.executeHandler(handler, event)
          )
        )
      }
    }
  }
  
  private async executeHandler(handler: EventHandler, event: Event) {
    try {
      await handler(event)
    } catch (error) {
      // Retry logic
      await this.retryHandler(handler, event, error)
    }
  }
}

Service Discovery ​

bash
/execute-task "Create service registry with health checking"

Part 4: Data Management (45 minutes) ​

Distributed Data Patterns ​

bash
/orchestrate "Implement distributed data patterns:
- Each service owns its data
- Event sourcing for order service
- CQRS for product catalog
- Cache-aside pattern
- Eventual consistency"

Event Sourcing Implementation ​

typescript
// services/order-service/src/event-store.ts
export class EventStore {
  async append(streamId: string, events: DomainEvent[]) {
    const stream = await this.getStream(streamId)
    
    for (const event of events) {
      await this.db.events.create({
        streamId,
        eventId: generateId(),
        eventType: event.type,
        eventData: event.data,
        eventVersion: stream.version + 1,
        timestamp: new Date()
      })
      
      stream.version++
    }
    
    // Publish to event bus
    await this.eventBus.publishBatch(events)
  }
  
  async getEvents(streamId: string, fromVersion = 0) {
    return await this.db.events.findMany({
      where: {
        streamId,
        eventVersion: { gte: fromVersion }
      },
      orderBy: { eventVersion: 'asc' }
    })
  }
  
  async getSnapshot(streamId: string) {
    const snapshot = await this.db.snapshots.findLatest(streamId)
    const events = await this.getEvents(streamId, snapshot?.version || 0)
    
    return {
      snapshot,
      events
    }
  }
}

// Order aggregate using event sourcing
export class Order {
  private events: DomainEvent[] = []
  private version = 0
  
  static async load(id: string): Promise<Order> {
    const { snapshot, events } = await eventStore.getSnapshot(id)
    
    const order = new Order(id)
    
    if (snapshot) {
      order.applySnapshot(snapshot)
    }
    
    for (const event of events) {
      order.apply(event)
    }
    
    return order
  }
  
  createOrder(data: CreateOrderData) {
    this.addEvent({
      type: 'OrderCreated',
      data: {
        orderId: this.id,
        userId: data.userId,
        items: data.items,
        total: data.total
      }
    })
  }
  
  private apply(event: DomainEvent) {
    switch (event.type) {
      case 'OrderCreated':
        this.status = 'created'
        this.items = event.data.items
        this.total = event.data.total
        break
      
      case 'OrderPaid':
        this.status = 'paid'
        this.paymentId = event.data.paymentId
        break
      
      case 'OrderShipped':
        this.status = 'shipped'
        this.trackingNumber = event.data.trackingNumber
        break
    }
    
    this.version++
  }
  
  async save() {
    await eventStore.append(this.id, this.events)
    this.events = []
  }
}

CQRS Implementation ​

bash
/execute-task "Implement CQRS for product catalog with separate read/write models"

Part 5: Resilience Patterns (45 minutes) ​

Circuit Breaker ​

typescript
// shared/resilience/circuit-breaker.ts
export class CircuitBreaker {
  private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED'
  private failures = 0
  private successCount = 0
  private lastFailureTime?: Date
  
  constructor(
    private options: {
      failureThreshold: number
      recoveryTimeout: number
      halfOpenRequests: number
    }
  ) {}
  
  async call<T>(fn: () => Promise<T>): Promise<T> {
    if (this.state === 'OPEN') {
      if (this.shouldAttemptReset()) {
        this.state = 'HALF_OPEN'
        this.successCount = 0
      } else {
        throw new CircuitOpenError('Circuit breaker is OPEN')
      }
    }
    
    try {
      const result = await fn()
      this.onSuccess()
      return result
    } catch (error) {
      this.onFailure()
      throw error
    }
  }
  
  private onSuccess() {
    this.failures = 0
    
    if (this.state === 'HALF_OPEN') {
      this.successCount++
      if (this.successCount >= this.options.halfOpenRequests) {
        this.state = 'CLOSED'
      }
    }
  }
  
  private onFailure() {
    this.failures++
    this.lastFailureTime = new Date()
    
    if (this.failures >= this.options.failureThreshold) {
      this.state = 'OPEN'
    }
  }
}

Retry with Backoff ​

typescript
// shared/resilience/retry.ts
export async function retryWithBackoff<T>(
  fn: () => Promise<T>,
  options: {
    maxRetries: number
    initialDelay: number
    maxDelay: number
    factor: number
  }
): Promise<T> {
  let lastError: Error
  
  for (let i = 0; i < options.maxRetries; i++) {
    try {
      return await fn()
    } catch (error) {
      lastError = error
      
      if (i < options.maxRetries - 1) {
        const delay = Math.min(
          options.initialDelay * Math.pow(options.factor, i),
          options.maxDelay
        )
        
        await sleep(delay + Math.random() * delay * 0.1) // Jitter
      }
    }
  }
  
  throw lastError!
}

Bulkhead Pattern ​

typescript
// shared/resilience/bulkhead.ts
export class Bulkhead {
  private queue: Array<() => void> = []
  private running = 0
  
  constructor(private concurrency: number) {}
  
  async execute<T>(fn: () => Promise<T>): Promise<T> {
    if (this.running >= this.concurrency) {
      await new Promise(resolve => this.queue.push(resolve))
    }
    
    this.running++
    
    try {
      return await fn()
    } finally {
      this.running--
      const next = this.queue.shift()
      if (next) next()
    }
  }
}

Part 6: Deployment & Monitoring (45 minutes) ​

Docker Compose ​

yaml
# docker-compose.yml
version: '3.8'

services:
  # API Gateway
  gateway:
    build: ./api-gateway
    ports:
      - "8080:8080"
    environment:
      - SERVICE_REGISTRY_URL=http://consul:8500
      - TRACING_ENDPOINT=http://jaeger:14268
    depends_on:
      - consul
      - jaeger

  # User Service
  user-service:
    build: ./services/user-service
    environment:
      - DB_URL=postgresql://postgres:password@user-db:5432/users
      - KAFKA_BROKERS=kafka:9092
      - SERVICE_NAME=user-service
    depends_on:
      - user-db
      - kafka

  # Product Service
  product-service:
    build: ./services/product-service
    environment:
      - DB_URL=postgresql://postgres:password@product-db:5432/products
      - SEARCH_URL=http://elasticsearch:9200
      - KAFKA_BROKERS=kafka:9092
    depends_on:
      - product-db
      - elasticsearch
      - kafka

  # Order Service with Event Store
  order-service:
    build: ./services/order-service
    environment:
      - EVENT_STORE_URL=postgresql://postgres:password@event-store:5432/events
      - KAFKA_BROKERS=kafka:9092
    depends_on:
      - event-store
      - kafka

  # Databases
  user-db:
    image: postgres:15
    environment:
      - POSTGRES_DB=users
      - POSTGRES_PASSWORD=password
    volumes:
      - user-data:/var/lib/postgresql/data

  product-db:
    image: postgres:15
    environment:
      - POSTGRES_DB=products
      - POSTGRES_PASSWORD=password
    volumes:
      - product-data:/var/lib/postgresql/data

  event-store:
    image: postgres:15
    environment:
      - POSTGRES_DB=events
      - POSTGRES_PASSWORD=password
    volumes:
      - event-data:/var/lib/postgresql/data

  # Infrastructure
  kafka:
    image: confluentinc/cp-kafka:latest
    environment:
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
      - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092

  consul:
    image: consul:latest
    ports:
      - "8500:8500"
    command: consul agent -server -bootstrap-expect=1 -ui -client=0.0.0.0

  jaeger:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"
      - "14268:14268"

  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin

volumes:
  user-data:
  product-data:
  event-data:

Kubernetes Deployment ​

bash
/execute-task "Create Kubernetes manifests for production deployment"
yaml
# k8s/user-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  labels:
    app: user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: micromart/user-service:latest
        ports:
        - containerPort: 8080
        env:
        - name: DB_URL
          valueFrom:
            secretKeyRef:
              name: user-db-secret
              key: url
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        resources:
          requests:
            memory: "256Mi"
            cpu: "200m"
          limits:
            memory: "512Mi"
            cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: user-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: user-service
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Monitoring Setup ​

typescript
// shared/monitoring/metrics.ts
import { Registry, Counter, Histogram, Gauge } from 'prom-client'

export class Metrics {
  private registry = new Registry()
  
  // HTTP metrics
  httpRequestDuration = new Histogram({
    name: 'http_request_duration_seconds',
    help: 'Duration of HTTP requests in seconds',
    labelNames: ['method', 'route', 'status_code'],
    buckets: [0.1, 0.5, 1, 2, 5]
  })
  
  httpRequestTotal = new Counter({
    name: 'http_requests_total',
    help: 'Total number of HTTP requests',
    labelNames: ['method', 'route', 'status_code']
  })
  
  // Business metrics
  ordersCreated = new Counter({
    name: 'orders_created_total',
    help: 'Total number of orders created',
    labelNames: ['payment_method', 'source']
  })
  
  orderValue = new Histogram({
    name: 'order_value_dollars',
    help: 'Order value in dollars',
    buckets: [10, 50, 100, 500, 1000, 5000]
  })
  
  // Service health
  serviceHealth = new Gauge({
    name: 'service_health',
    help: 'Service health status (1 = healthy, 0 = unhealthy)',
    labelNames: ['service']
  })
  
  constructor() {
    this.registry.registerMetric(this.httpRequestDuration)
    this.registry.registerMetric(this.httpRequestTotal)
    this.registry.registerMetric(this.ordersCreated)
    this.registry.registerMetric(this.orderValue)
    this.registry.registerMetric(this.serviceHealth)
  }
  
  async getMetrics() {
    return this.registry.metrics()
  }
}

Testing the System ​

End-to-End Test ​

bash
# 1. Start all services
docker-compose up -d

# 2. Register a user
curl -X POST http://localhost:8080/api/user/users/register \
  -H "Content-Type: application/json" \
  -d '{"email": "test@example.com", "password": "secure123", "name": "Test User"}'

# 3. Search products
curl http://localhost:8080/api/product/products/search?q=laptop&category=electronics

# 4. Create order
curl -X POST http://localhost:8080/api/order/orders \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {"productId": "prod123", "quantity": 1}
    ],
    "shippingAddress": {...}
  }'

# 5. Check service health
curl http://localhost:8080/health

Load Testing ​

bash
/execute-task "Create load testing scenarios for microservices"
javascript
// k6-load-test.js
import http from 'k6/http'
import { check, sleep } from 'k6'

export let options = {
  stages: [
    { duration: '2m', target: 100 },
    { duration: '5m', target: 500 },
    { duration: '2m', target: 1000 },
    { duration: '5m', target: 1000 },
    { duration: '2m', target: 0 }
  ],
  thresholds: {
    http_req_duration: ['p(99)<500'],
    http_req_failed: ['rate<0.1']
  }
}

export default function() {
  // User registration
  let registerRes = http.post(
    'http://localhost:8080/api/user/users/register',
    JSON.stringify({
      email: `user${Date.now()}@example.com`,
      password: 'test123',
      name: 'Load Test User'
    }),
    { headers: { 'Content-Type': 'application/json' } }
  )
  
  check(registerRes, {
    'registration successful': (r) => r.status === 200
  })
  
  let token = registerRes.json('token')
  
  // Search products
  let searchRes = http.get(
    'http://localhost:8080/api/product/products/search?q=test'
  )
  
  check(searchRes, {
    'search successful': (r) => r.status === 200
  })
  
  // Create order
  let orderRes = http.post(
    'http://localhost:8080/api/order/orders',
    JSON.stringify({
      items: [{ productId: 'test-product', quantity: 1 }]
    }),
    { 
      headers: { 
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
      } 
    }
  )
  
  check(orderRes, {
    'order created': (r) => r.status === 201
  })
  
  sleep(1)
}

Production Considerations ​

Security ​

  • mTLS between services
  • API Gateway authentication
  • Secrets management
  • Network policies

Scalability ​

  • Horizontal pod autoscaling
  • Database sharding
  • Caching strategies
  • CDN integration

Reliability ​

  • Circuit breakers
  • Retry mechanisms
  • Health checks
  • Graceful shutdowns

Observability ​

  • Distributed tracing
  • Centralized logging
  • Metrics aggregation
  • Alerting rules

What You've Built ​

βœ… Complete microservices architecture βœ… Event-driven communication βœ… Service discovery & load balancing βœ… Distributed data management βœ… Resilience patterns βœ… Production-ready deployment βœ… Comprehensive monitoring

Next Steps ​

Your microservices platform is ready! Consider:

  1. Service Mesh: Add Istio for advanced traffic management
  2. CI/CD: Implement GitOps with ArgoCD
  3. Security: Add OAuth2/OIDC with Keycloak
  4. Data Pipeline: Add Apache Kafka for streaming
  5. Machine Learning: Add recommendation service
  6. Edge Computing: Deploy services to edge locations

Resources ​

Congratulations! You've built a production-grade microservices system in 5 hours!

Built with ❀️ for the AI Coding community, by Praney Behl