KyoMel / Yogyakarta, Indonesia

Term 091091 / 344

Bulkhead Pattern

Month
October 2025
Day
21
Source
2025/october-term.md

Definition:

Bulkhead Pattern is a fault tolerance design pattern that isolates critical resources and functionality into separate pools to prevent failures in one area from cascading and bringing down the entire system. Named after ship bulkheads that prevent water from spreading between compartments, this pattern compartmentalizes system components so that if one fails, others continue operating normally.

Key Properties:

  • Resource isolation: Separate pools for different operations
  • Failure containment: Problems don’t spread across boundaries
  • Independent scaling: Each compartment can scale separately
  • Performance protection: Critical operations stay unaffected
  • Resource allocation: Guaranteed resources for important functions

Core Concept: Instead of sharing resources, create separate “compartments” for different types of operations or users.

Example:

E-commerce Platform

class EcommercePlatform {
  constructor() {
    this.setupBulkheads();
  }

  setupBulkheads() {
    // Customer-facing bulkhead (highest priority)
    this.customerBulkhead = {
      database: new ConnectionPool({ max: 15, min: 10 }),
      cache: new RedisPool({ max: 10, min: 5 }),
      threadPool: new ThreadPool({ core: 8, max: 15 }),
      rateLimiter: new RateLimiter({ rpm: 10000 })
    };

    // Admin operations bulkhead (medium priority)
    this.adminBulkhead = {
      database: new ConnectionPool({ max: 8, min: 3 }),
      cache: new RedisPool({ max: 5, min: 2 }),
      threadPool: new ThreadPool({ core: 3, max: 8 }),
      rateLimiter: new RateLimiter({ rpm: 1000 })
    };

    // Analytics bulkhead (lowest priority)
    this.analyticsBulkhead = {
      database: new ReadReplicaPool({ max: 5, min: 2 }),
      cache: new RedisPool({ max: 3, min: 1 }),
      threadPool: new ThreadPool({ core: 2, max: 5 }),
      rateLimiter: new RateLimiter({ rpm: 100 })
    };

    // Background jobs bulkhead
    this.backgroundBulkhead = {
      database: new ConnectionPool({ max: 3, min: 1 }),
      threadPool: new ThreadPool({ core: 2, max: 4 }),
      rateLimiter: new RateLimiter({ rpm: 50 })
    };
  }

  // Customer operations - highest priority resources
  async placeOrder(customerId, orderData) {
    return await this.executeInBulkhead('customer', async () => {
      console.log('🛒 Processing customer order');

      const connection = await this.customerBulkhead.database.getConnection();
      const cache = await this.customerBulkhead.cache.getClient();

      try {
        // Check inventory
        const inventory = await cache.get(`inventory:${orderData.productId}`);

        if (!inventory || inventory < orderData.quantity) {
          const dbInventory = await connection.query(
            'SELECT quantity FROM inventory WHERE product_id = ?',
            [orderData.productId]
          );

          if (dbInventory.quantity < orderData.quantity) {
            throw new Error('Insufficient inventory');
          }
        }

        // Create order
        const order = await connection.query(
          'INSERT INTO orders (customer_id, product_id, quantity) VALUES (?, ?, ?)',
          [customerId, orderData.productId, orderData.quantity]
        );

        // Update cache
        await cache.decr(`inventory:${orderData.productId}`, orderData.quantity);

        return { orderId: order.insertId, status: 'confirmed' };

      } finally {
        connection.release();
      }
    });
  }

  // Admin operations - medium priority resources
  async updateProductInfo(productId, updates) {
    return await this.executeInBulkhead('admin', async () => {
      console.log('⚙️ Admin updating product');

      const connection = await this.adminBulkhead.database.getConnection();

      try {
        return await connection.query(
          'UPDATE products SET name = ?, price = ? WHERE id = ?',
          [updates.name, updates.price, productId]
        );
      } finally {
        connection.release();
      }
    });
  }

  // Analytics - lowest priority resources
  async generateSalesReport(startDate, endDate) {
    return await this.executeInBulkhead('analytics', async () => {
      console.log('📈 Generating analytics report');

      const connection = await this.analyticsBulkhead.database.getConnection();

      try {
        // Heavy analytical query
        return await connection.query(`
          SELECT
            DATE(created_at) as date,
            COUNT(*) as orders,
            SUM(total) as revenue,
            AVG(total) as avg_order_value
          FROM orders o
          JOIN order_items oi ON o.id = oi.order_id
          JOIN products p ON oi.product_id = p.id
          WHERE o.created_at BETWEEN ? AND ?
          GROUP BY DATE(created_at)
          ORDER BY date
        `, [startDate, endDate]);
      } finally {
        connection.release();
      }
    });
  }

  // Background tasks - separate resources
  async processEmailQueue() {
    return await this.executeInBulkhead('background', async () => {
      console.log('📧 Processing background emails');

      const connection = await this.backgroundBulkhead.database.getConnection();

      try {
        const pendingEmails = await connection.query(
          'SELECT * FROM email_queue WHERE status = "pending" LIMIT 100'
        );

        for (const email of pendingEmails) {
          await this.sendEmail(email);
          await connection.query(
            'UPDATE email_queue SET status = "sent" WHERE id = ?',
            [email.id]
          );
        }

        return { processed: pendingEmails.length };
      } finally {
        connection.release();
      }
    });
  }

  async executeInBulkhead(bulkheadType, operation) {
    const bulkhead = this.getBulkhead(bulkheadType);

    // Check rate limiting
    if (!await bulkhead.rateLimiter.allowRequest()) {
      throw new Error(`Rate limit exceeded for ${bulkheadType} operations`);
    }

    // Execute in thread pool
    return await bulkhead.threadPool.execute(operation);
  }

  getBulkhead(type) {
    const bulkheads = {
      'customer': this.customerBulkhead,
      'admin': this.adminBulkhead,
      'analytics': this.analyticsBulkhead,
      'background': this.backgroundBulkhead
    };

    return bulkheads[type];
  }

  // Monitoring and health checks
  async getBulkheadStatus() {
    return {
      customer: {
        activeConnections: this.customerBulkhead.database.activeConnections,
        queueLength: this.customerBulkhead.threadPool.queueLength,
        rateLimitRemaining: this.customerBulkhead.rateLimiter.remaining
      },
      admin: {
        activeConnections: this.adminBulkhead.database.activeConnections,
        queueLength: this.adminBulkhead.threadPool.queueLength
      },
      analytics: {
        activeConnections: this.analyticsBulkhead.database.activeConnections,
        queueLength: this.analyticsBulkhead.threadPool.queueLength
      },
      background: {
        activeConnections: this.backgroundBulkhead.database.activeConnections,
        queueLength: this.backgroundBulkhead.threadPool.queueLength
      }
    };
  }
}

// Usage example
const platform = new EcommercePlatform();

// Simulate different types of load
async function simulateLoad() {
  const results = await Promise.allSettled([
    // Customer operations (critical) - will always work
    platform.placeOrder('customer123', { productId: 1, quantity: 2 }),
    platform.placeOrder('customer456', { productId: 2, quantity: 1 }),

    // Admin operations (medium priority) - works if resources available
    platform.updateProductInfo(1, { name: 'New Product Name', price: 29.99 }),

    // Analytics (low priority) - might be throttled
    platform.generateSalesReport('2023-01-01', '2023-12-31'),

    // Background tasks (lowest priority) - runs when possible
    platform.processEmailQueue()
  ]);

  console.log('Results:', results.map(r => r.status));

  // Check bulkhead health
  const status = await platform.getBulkheadStatus();
  console.log('Bulkhead Status:', status);
}

simulateLoad();

Keep reading