> ## Documentation Index
> Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulkhead

> Bulkhead pattern middleware for isolating failures and limiting concurrency.

## Overview

The `bulkhead` middleware implements the bulkhead pattern, limiting concurrent requests to prevent cascade failures and ensure fair resource allocation.

Use it when you need:

* Failure isolation between services
* Concurrent request limiting
* Resource protection

## Installation

```go theme={null}
import "github.com/go-mizu/mizu/middlewares/bulkhead"
```

## Quick Start

```go theme={null}
app := mizu.New()

// Limit to 10 concurrent requests
app.Use(bulkhead.New(10))
```

## Configuration

### Options

| Option          | Type                    | Default  | Description                       |
| --------------- | ----------------------- | -------- | --------------------------------- |
| `MaxConcurrent` | `int`                   | Required | Max concurrent requests           |
| `MaxWaiting`    | `int`                   | `0`      | Max waiting requests (0 = reject) |
| `Timeout`       | `time.Duration`         | `0`      | Wait timeout                      |
| `ErrorHandler`  | `func(*mizu.Ctx) error` | -        | Custom rejection handler          |

## Examples

### Simple Limit

```go theme={null}
// Reject if more than 10 concurrent
app.Use(bulkhead.New(10))
```

### With Waiting Queue

```go theme={null}
// Allow 10 concurrent, 20 waiting
app.Use(bulkhead.WithOptions(bulkhead.Options{
    MaxConcurrent: 10,
    MaxWaiting:    20,
}))
```

### With Timeout

```go theme={null}
// Wait up to 5 seconds for slot
app.Use(bulkhead.WithOptions(bulkhead.Options{
    MaxConcurrent: 10,
    MaxWaiting:    50,
    Timeout:       5 * time.Second,
}))
```

### Per-Route Limits

```go theme={null}
// Different limits for different routes
api := app.Group("/api")
api.Use(bulkhead.New(100))

heavy := app.Group("/heavy")
heavy.Use(bulkhead.New(5))
```

### Custom Error

```go theme={null}
app.Use(bulkhead.WithOptions(bulkhead.Options{
    MaxConcurrent: 10,
    ErrorHandler: func(c *mizu.Ctx) error {
        return c.JSON(503, map[string]string{
            "error": "Service temporarily unavailable",
        })
    },
}))
```

## API Reference

### Functions

```go theme={null}
// New creates bulkhead with max concurrent
func New(maxConcurrent int) mizu.Middleware

// WithOptions creates bulkhead with configuration
func WithOptions(opts Options) mizu.Middleware
```

## How It Works

1. Request arrives
2. Check if under concurrent limit
3. If under: acquire slot, process, release
4. If over: check waiting queue
5. If queue full or timeout: reject with 503

## HTTP Status Codes

| Code | Meaning                             |
| ---- | ----------------------------------- |
| 503  | Service unavailable (bulkhead full) |

## Technical Details

### Implementation

The bulkhead middleware uses a semaphore pattern with buffered channels to control concurrency:

* **Semaphore Channel**: A buffered channel with capacity equal to `MaxConcurrent` acts as the semaphore for slot allocation
* **Waiting Queue**: A counter tracks the number of requests waiting for a slot, capped at `MaxWait`
* **Non-blocking Acquire**: First attempts to acquire a slot without blocking using `select` with `default`
* **Blocking Wait**: If no slot is available, increments the waiting counter and blocks until a slot becomes available or context is cancelled
* **Thread Safety**: Uses `sync.Mutex` to protect the waiting counter and ensure thread-safe operations

### Core Components

**Bulkhead Structure**:

* `sem chan struct{}`: Buffered channel for semaphore-based slot management
* `waiting int`: Current number of requests in the waiting queue
* `maxWait int`: Maximum allowed requests in the waiting queue
* `mu sync.Mutex`: Mutex for protecting shared state

**Manager**:

* Manages multiple named bulkheads for isolation between different services or paths
* Thread-safe bulkhead creation and retrieval using `sync.RWMutex`
* Provides aggregated statistics across all managed bulkheads

**Statistics**:

* Real-time metrics including active requests, waiting requests, and available slots
* Useful for monitoring and debugging bulkhead behavior

### Request Flow

1. Request arrives at middleware
2. Attempts non-blocking slot acquisition via `select` statement
3. If slot acquired: processes request and releases slot via `defer`
4. If no slot available:
   * Checks if waiting queue is full
   * If full: rejects immediately with error handler or 503 status
   * If space available: increments waiting counter and blocks on semaphore channel
5. When slot becomes available or context cancelled: decrements waiting counter
6. On context cancellation: returns context error (e.g., timeout, cancellation)

## Best Practices

* Set limits based on resource capacity
* Use different bulkheads for different services
* Monitor rejection rates
* Combine with circuit breaker for full resilience

## Testing

### Test Coverage

| Test Case                      | Description                                                 | Expected Behavior                                                                     |
| ------------------------------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `TestNew`                      | Tests basic bulkhead functionality with concurrent requests | Some requests succeed (200), others are rejected (503) when bulkhead is full          |
| `TestBulkhead_Stats`           | Validates bulkhead statistics reporting                     | Returns correct name, max active count, and available slots                           |
| `TestNewBulkhead_ErrorHandler` | Tests custom error handler for rejected requests            | Rejected requests use custom error handler with 429 status instead of default 503     |
| `TestManager`                  | Tests bulkhead manager's get-or-create behavior             | Returns same bulkhead instance for same name, different instances for different names |
| `TestManager_Stats`            | Validates manager's aggregated statistics                   | Returns stats for all managed bulkheads by name                                       |
| `TestForPath`                  | Tests path-based bulkhead isolation                         | Creates separate bulkheads for different URL paths                                    |
| `TestDefaults`                 | Validates default configuration values                      | Uses default values of 10 for MaxConcurrent and MaxWait when not specified            |

## Related Middlewares

* [circuitbreaker](/middlewares/circuitbreaker) - Circuit breaker pattern
* [ratelimit](/middlewares/ratelimit) - Rate limiting
* [concurrency](/middlewares/concurrency) - Concurrency control
