Overview
Thebulkhead 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
Quick Start
Configuration
Options
Examples
Simple Limit
With Waiting Queue
With Timeout
Per-Route Limits
Custom Error
API Reference
Functions
How It Works
- Request arrives
- Check if under concurrent limit
- If under: acquire slot, process, release
- If over: check waiting queue
- If queue full or timeout: reject with 503
HTTP Status Codes
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
MaxConcurrentacts 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
selectwithdefault - 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.Mutexto protect the waiting counter and ensure thread-safe operations
Core Components
Bulkhead Structure:sem chan struct{}: Buffered channel for semaphore-based slot managementwaiting int: Current number of requests in the waiting queuemaxWait int: Maximum allowed requests in the waiting queuemu sync.Mutex: Mutex for protecting shared state
- 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
- Real-time metrics including active requests, waiting requests, and available slots
- Useful for monitoring and debugging bulkhead behavior
Request Flow
- Request arrives at middleware
- Attempts non-blocking slot acquisition via
selectstatement - If slot acquired: processes request and releases slot via
defer - 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
- When slot becomes available or context cancelled: decrements waiting counter
- 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
Related Middlewares
- circuitbreaker - Circuit breaker pattern
- ratelimit - Rate limiting
- concurrency - Concurrency control