System Design Patterns

Essential system design patterns:

Load Balancing Strategies

Round Robin: Request 1 → Server A, Request 2 → Server B, Request 3 → Server C
Least Connections: Route to server with fewest active connections
Weighted: Assign different weights based on server capacity
IP Hash: Route based on client IP hash for session affinity

Caching Patterns

// Cache-Aside Pattern
const getUser = async (userId) => {
  // Try cache first
  let user = await cache.get(`user:${userId}`);
  if (!user) {
    // Cache miss - fetch from database
    user = await database.getUser(userId);
    await cache.set(`user:${userId}`, user, 3600); // 1 hour TTL
  }
  return user;
};

// Write-Through Pattern
const updateUser = async (userId, userData) => {
  // Update database first
  const user = await database.updateUser(userId, userData);
  // Then update cache
  await cache.set(`user:${userId}`, user, 3600);
  return user;
};

Database Patterns

Master-Slave Replication:
- Master handles writes
- Slaves handle reads
- Eventual consistency

Database Sharding:
- Horizontal partitioning
- Shard by user ID, geography, or feature
- Each shard is independent

CQRS (Command Query Responsibility Segregation):
- Separate read and write models
- Optimize each for its specific use case

Microservices Communication

Synchronous:
- HTTP/REST APIs
- GraphQL
- gRPC

Asynchronous:
- Message queues (RabbitMQ, SQS)
- Event streaming (Kafka)
- Pub/Sub patterns

Scalability Patterns

  • Horizontal Scaling: Add more servers
  • Vertical Scaling: Upgrade server hardware
  • Auto Scaling: Dynamic scaling based on metrics
  • Circuit Breaker: Prevent cascade failures
  • Bulkhead: Isolate critical resources