BelajarKoding Logobelajarkoding

Platform belajar web development Indonesia. Artikel, cheat sheets, roadmap, dan code challenges untuk developer Indonesia.

Navigasi

  • Artikel
  • Cheat Sheets
  • Roadmap
  • Challenges
  • Pricing
  • Search

Produk Lain

  • JagoHermes
  • KelasClaude
  • KilatKoding
  • BelajarVibeCoding
  • JualanKoding

Support

  • Privacy Policy
  • Terms of Service
  • Email

© 2026 BelajarKoding. All rights reserved.

Galih PratamaBagian dari ekosistem Galih Pratama
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade
belajarkoding LogobyGalih Pratama
RoadmapArtikelCheat SheetsChallengesUpgrade

Daftar Isi

Core PrinciplesWhen to UseCommunication PatternsSynchronous (HTTP/REST)Asynchronous (Message Queue)gRPC (High Performance)Resilience PatternsCircuit BreakerRetry with Exponential BackoffTimeoutFallbackAPI Gateway PatternService DiscoveryClient-SideServer-Side (Kubernetes)Data ManagementDatabase Per ServiceSaga PatternEvent SourcingCQRS (Command Query Responsibility Segregation)ObservabilityDistributed TracingStructured LoggingHealth ChecksDeployment PatternsBlue-Green DeploymentCanary DeploymentRolling DeploymentSecurityAuthenticationService-to-Service AuthCommon ToolsMessage QueuesAPI GatewaysService MeshOrchestrationMonitoringTracingBest PracticesAnti-PatternsMigration StrategyStrangler Fig PatternQuick Decision MatrixResources
MicroservicesArchitectureBackendDesign Patterns

Microservices Architecture Cheat Sheet

Quick reference microservices patterns. Communication, resilience, data management, API gateway, service discovery, dan best practices.

TypeScript7 min read1.353 kata
Cheat sheet ini adalah konten premium. Login atau daftar untuk mengakses konten premium.

#Core Principles

Prinsip-prinsip fundamental yang menjadi dasar arsitektur microservices.

PrincipleDescription
Single ResponsibilityOne service = one business capability
AutonomousIndependent deployment & database
Loose CouplingMinimal dependencies between services
ResilientFailures don't cascade
ObservableComprehensive logging & monitoring

#When to Use

Situasi-situasi dimana microservices cocok digunakan atau tidak cocok.

Good for:

  • Large, complex apps
  • Multiple teams (>10 developers)
  • Independent scaling needs
  • Different tech requirements

Bad for:

  • Small projects
  • MVP/Prototypes
  • Small teams (<5 people)
  • Limited budget/time

#Communication Patterns

Berbagai cara komunikasi antar microservices.

#Synchronous (HTTP/REST)

Komunikasi real-time menggunakan HTTP calls langsung.

typescript
// Service A calls Service B
const response = await fetch('http://service-b/api/endpoint');
const data = await response.json();

Kelebihan: Simple, immediate response Kekurangan: Tight coupling, blocking, cascading failures

#Asynchronous (Message Queue)

typescript
// Service A publishes event
await messageQueue.publish('order.created', { orderId: '123' });
 
// Service B subscribes
messageQueue.subscribe('order.created', async (event) => {
 await processOrder(event.orderId);
});

Kelebihan: Loose coupling, fault-tolerant, async Kekurangan: Complex, eventual consistency

#gRPC (High Performance)

typescript
// Define proto
service UserService {
 rpc GetUser (UserRequest) returns (UserResponse);
}
 
// Client
const response = await client.getUser({ id: '123' });

Kelebihan: Fast, type-safe, bidirectional streaming Kekurangan: More setup, HTTP/2 required

#Resilience Patterns

#Circuit Breaker

typescript
class CircuitBreaker {
 state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
 failures = 0;
 threshold = 5;
 
 async call(fn: Function) {
  if (this.state === 'OPEN') {
   throw new Error('Circuit breaker open');
  }
 
  try {
   const result = await fn();
   this.onSuccess();
   return result;
  } catch (error) {
   this.onFailure();
   throw error;
  }
 }
 
 private onSuccess() {
  this.failures = 0;
  this.state = 'CLOSED';
 }
 
 private onFailure() {
  this.failures++;
  if (this.failures >= this.threshold) {
   this.state = 'OPEN';
   setTimeout(() => this.state = 'HALF_OPEN', 60000);
  }
 }
}

#Retry with Exponential Backoff

typescript
async function retry(fn: Function, maxRetries = 3) {
 for (let i = 0; i < maxRetries; i++) {
  try {
   return await fn();
  } catch (error) {
   if (i === maxRetries - 1) throw error;
   await sleep(Math.pow(2, i) * 1000); // 1s, 2s, 4s
  }
 }
}

#Timeout

typescript
async function withTimeout(fn: Function, ms = 5000) {
 return Promise.race([
  fn(),
  new Promise((_, reject) =>
   setTimeout(() => reject(new Error('Timeout')), ms)
  )
 ]);
}

#Fallback

typescript
async function getUser(id: string) {
 try {
  return await fetchFromService(id);
 } catch (error) {
  return getCachedUser(id); // Fallback
 }
}

#API Gateway Pattern

plaintext
Client → API Gateway → [Services]
 
API Gateway:
- Routing
- Authentication
- Rate limiting
- Request/response transformation
- Load balancing
typescript
// Express.js example
import { createProxyMiddleware } from 'http-proxy-middleware';
 
app.use('/api/users', createProxyMiddleware({
 target: 'http://user-service:3000',
 changeOrigin: true
}));
 
app.use('/api/orders', createProxyMiddleware({
 target: 'http://order-service:3001',
 changeOrigin: true
}));

#Service Discovery

#Client-Side

typescript
const registry = {
 'user-service': 'http://user-service:3000',
 'order-service': 'http://order-service:3001'
};
 
const url = registry['user-service'];
const response = await fetch(`${url}/api/users/123`);

#Server-Side (Kubernetes)

yaml
apiVersion: v1
kind: Service
metadata:
 name: user-service
spec:
 selector:
  app: user
 ports:
  - port: 80
   targetPort: 3000

#Data Management

#Database Per Service

plaintext
User Service  → PostgreSQL
Order Service  → MongoDB
Payment Service → PostgreSQL

Manfaat: Autonomy, tech diversity, independent scaling Challenges: No joins, data consistency

#Saga Pattern

Distributed transactions:

typescript
async function orderSaga(order) {
 try {
  // Step 1: Create order
  const orderId = await orderService.create(order);
 
  try {
   // Step 2: Process payment
   await paymentService.charge(order.amount);
 
   try {
    // Step 3: Reserve inventory
    await inventoryService.reserve(order.items);
    await orderService.confirm(orderId);
   } catch {
    await paymentService.refund(order.amount);
    throw error;
   }
  } catch {
   await orderService.cancel(orderId);
   throw error;
  }
 } catch (error) {
  console.error('Saga failed:', error);
 }
}

#Event Sourcing

typescript
// Store events
const events = [
 { type: 'OrderCreated', orderId: '123', amount: 100 },
 { type: 'PaymentProcessed', orderId: '123' },
 { type: 'OrderShipped', orderId: '123' }
];
 
// Rebuild state from events
function getOrderState(orderId) {
 return events
  .filter(e => e.orderId === orderId)
  .reduce((state, event) => applyEvent(state, event), {});
}

#CQRS (Command Query Responsibility Segregation)

typescript
// Write model
class OrderCommandService {
 async createOrder(data) {
  const order = await this.db.insert(data);
  await this.eventBus.publish('order.created', order);
  return order;
 }
}
 
// Read model (optimized for queries)
class OrderQueryService {
 async getOrder(id) {
  return this.readDb.findById(id); // Denormalized data
 }
 
 async getOrdersByUser(userId) {
  return this.readDb.find({ userId });
 }
}

#Observability

#Distributed Tracing

typescript
// Generate trace ID
const traceId = generateUUID();
 
// Pass to downstream services
await fetch('http://service-b/api/endpoint', {
 headers: {
  'X-Trace-Id': traceId
 }
});
 
// Log with trace ID
logger.info('Order created', {
 traceId,
 orderId: order.id,
 service: 'order-service'
});

#Structured Logging

typescript
logger.info('User logged in', {
 userId: user.id,
 timestamp: new Date(),
 service: 'auth-service',
 traceId: req.headers['x-trace-id']
});

#Health Checks

typescript
app.get('/health', async (req, res) => {
 const health = {
  status: 'healthy',
  timestamp: new Date(),
  checks: {
   database: await checkDatabase(),
   redis: await checkRedis(),
   messageQueue: await checkQueue()
  }
 };
 
 const isHealthy = Object.values(health.checks).every(c => c === 'ok');
 res.status(isHealthy ? 200 : 503).json(health);
});

#Deployment Patterns

#Blue-Green Deployment

plaintext
Blue (old) → 100% traffic
Green (new) → 0% traffic
 
Deploy Green → Test
 
Switch traffic:
Blue → 0%
Green → 100%

#Canary Deployment

plaintext
v1.0 → 90% traffic
v2.0 → 10% traffic (canary)
 
If metrics good:
v1.0 → 50%
v2.0 → 50%
 
Then:
v1.0 → 0%
v2.0 → 100%

#Rolling Deployment

plaintext
3 instances:
1. Update instance 1 → wait
2. Update instance 2 → wait
3. Update instance 3 → done

#Security

#Authentication

typescript
// API Gateway validates JWT
app.use(async (req, res, next) => {
 const token = req.headers.authorization?.split(' ')[1];
 
 try {
  const decoded = jwt.verify(token, SECRET);
  req.user = decoded;
  next();
 } catch (error) {
  res.status(401).json({ error: 'Unauthorized' });
 }
});

#Service-to-Service Auth

typescript
// Use mTLS or service tokens
const response = await fetch('http://service-b/api/endpoint', {
 headers: {
  'Authorization': `Bearer ${serviceToken}`,
  'X-Service-Name': 'service-a'
 }
});

#Common Tools

#Message Queues

  • RabbitMQ
  • Apache Kafka
  • Redis Pub/Sub
  • AWS SQS

#API Gateways

  • Kong
  • Nginx
  • Traefik
  • AWS API Gateway

#Service Mesh

  • Istio
  • Linkerd
  • Consul

#Orchestration

  • Kubernetes
  • Docker Swarm
  • Nomad

#Monitoring

  • Prometheus + Grafana
  • Datadog
  • New Relic
  • ELK Stack

#Tracing

  • Jaeger
  • Zipkin
  • OpenTelemetry

#Best Practices

  • One database per service
  • API versioning (/api/v1/users)
  • Idempotent operations
  • Circuit breakers for external calls
  • Centralized logging with trace IDs
  • Health check endpoints
  • Graceful shutdown
  • Use message queues for async
  • Automate deployment (CI/CD)
  • Monitor everything (metrics, logs, traces)

#Anti-Patterns

Distributed Monolith

  • Microservices sharing same database
  • Synchronous calls between all services

Nanoservices

  • Too many tiny services
  • Excessive network overhead

Shared Database

  • Multiple services accessing same tables
  • No service autonomy

No API Gateway

  • Clients calling services directly
  • Scattered auth/rate limiting

Ignoring Failures

  • No circuit breakers
  • No retries/timeouts

#Migration Strategy

#Strangler Fig Pattern

plaintext
1. Identify module to extract
2. Build microservice alongside monolith
3. Route some traffic to new service
4. Gradually increase traffic
5. Remove code from monolith
6. Repeat for next module
plaintext
Monolith (100%) → Monolith (90%) + Service A (10%)
        → Monolith (50%) + Service A (50%)
        → Monolith (0%) + Service A (100%)

#Quick Decision Matrix

FactorMonolithMicroservices
Team size< 5> 10
ComplexitySimpleComplex
Deployment frequencyWeeks/monthsDaily/hourly
Scaling needsUniformVariable
Tech diversitySingle stackMultiple stacks
Time to marketFastSlower initially
Operational overheadLowHigh

#Resources

  • Microservices.io
  • Martin Fowler - Microservices
  • Chris Richardson - Microservices Patterns
  • Sam Newman - Building Microservices

Happy architecting! 🏗️

Baca Cheat Sheet Lengkap

Login untuk mengakses konten premium ini.

LoginDaftar Gratis
Share: