Skip to content
StackPractices
intermediate By Mathias Paulenko

Chain of Responsibility Pattern

Pass requests along a chain of handlers until one handles it. A behavioral design pattern for decoupling senders and receivers.

Topics: design

Note: This guide follows English-language naming conventions and terminology standards common in international development teams. Examples use English identifiers and comments to maximize compatibility across codebases and tooling.

Chain of Responsibility Pattern

Overview

The Chain of Responsibility Pattern is a behavioral design pattern that lets you pass requests along a chain of handlers. Each handler decides either to process the request or to pass it to the next handler in the chain. This decouples senders from receivers and allows multiple objects to handle a request without the sender knowing which one will process it.

When to Use

Use the Chain of Responsibility Pattern when:

  • More than one object may handle a request, and the handler isn’t known in advance
  • You want to issue a request to one of several objects without specifying the receiver explicitly
  • The set of objects that can handle a request should be specified dynamically
  • You need a pipeline or middleware where each step can process, transform, or stop a request

Solution

Python

from abc import ABC, abstractmethod
from typing import Optional

class Handler(ABC):
    def __init__(self):
        self._next: Optional['Handler'] = None

    def set_next(self, handler: 'Handler') -> 'Handler':
        self._next = handler
        return handler  # Enable fluent chaining

    @abstractmethod
    def handle(self, request: str) -> Optional[str]:
        pass

    def _pass_to_next(self, request: str) -> Optional[str]:
        if self._next:
            return self._next.handle(request)
        return None

class AuthHandler(Handler):
    def handle(self, request: str) -> Optional[str]:
        if not request.startswith("token:"):
            return "401 Unauthorized"
        return self._pass_to_next(request)

class RateLimitHandler(Handler):
    def __init__(self):
        super().__init__()
        self.requests = 0
        self.limit = 3

    def handle(self, request: str) -> Optional[str]:
        self.requests += 1
        if self.requests > self.limit:
            return "429 Too Many Requests"
        return self._pass_to_next(request)

class DataHandler(Handler):
    def handle(self, request: str) -> Optional[str]:
        return f"Processed: {request}"

# Build the chain
handler = AuthHandler()
handler.set_next(RateLimitHandler()).set_next(DataHandler())

print(handler.handle("token:abc123"))  # Processed
print(handler.handle("bad-request"))    # 401 Unauthorized

JavaScript

class Handler {
  constructor() {
    this.nextHandler = null;
  }

  setNext(handler) {
    this.nextHandler = handler;
    return handler;
  }

  handle(request) {
    if (this.nextHandler) {
      return this.nextHandler.handle(request);
    }
    return null;
  }
}

class AuthHandler extends Handler {
  handle(request) {
    if (!request.startsWith("token:")) {
      return "401 Unauthorized";
    }
    return super.handle(request);
  }
}

class RateLimitHandler extends Handler {
  constructor() {
    super();
    this.requests = 0;
    this.limit = 3;
  }

  handle(request) {
    this.requests++;
    if (this.requests > this.limit) {
      return "429 Too Many Requests";
    }
    return super.handle(request);
  }
}

class DataHandler extends Handler {
  handle(request) {
    return `Processed: ${request}`;
  }
}

// Build the chain
const handler = new AuthHandler();
handler.setNext(new RateLimitHandler()).setNext(new DataHandler());

console.log(handler.handle("token:abc123")); // Processed
console.log(handler.handle("bad-request"));     // 401

Java

public abstract class Handler {
    protected Handler next;

    public Handler setNext(Handler next) {
        this.next = next;
        return next;
    }

    public abstract String handle(String request);

    protected String passToNext(String request) {
        if (next != null) {
            return next.handle(request);
        }
        return null;
    }
}

public class AuthHandler extends Handler {
    @Override
    public String handle(String request) {
        if (!request.startsWith("token:")) {
            return "401 Unauthorized";
        }
        return passToNext(request);
    }
}

public class RateLimitHandler extends Handler {
    private int requests = 0;
    private final int limit = 3;

    @Override
    public String handle(String request) {
        requests++;
        if (requests > limit) {
            return "429 Too Many Requests";
        }
        return passToNext(request);
    }
}

public class DataHandler extends Handler {
    @Override
    public String handle(String request) {
        return "Processed: " + request;
    }
}

// Build the chain
Handler handler = new AuthHandler();
handler.setNext(new RateLimitHandler()).setNext(new DataHandler());

System.out.println(handler.handle("token:abc")); // Processed
System.out.println(handler.handle("bad"));        // 401

Explanation

The Chain of Responsibility Pattern has two roles:

  • Handler Interface — declares a handle() method and maintains a reference to the next handler
  • Concrete Handlers — implement processing logic; each decides whether to handle the request or pass it along

The client builds the chain order. Each handler can also choose to stop the chain (short-circuit) by returning early without calling the next handler.

Variants

VariantStructureBest For
Linear ChainLinked list of handlersSimple sequential processing
Tree ChainHandlers organized hierarchicallyMulti-level decision trees
Middleware PipelineArray of functions, each calls next()Web frameworks (Express, Django middleware)
Event BusHandlers register for specific eventsDecoupled event-driven systems

What Works

  • Keep handlers focused — each handler should do one thing (auth, validation, logging, etc.)
  • Provide a default handler at the end of the chain to avoid unhandled requests
  • Allow chain modification at runtime by exposing setNext() or addHandler() methods
  • Use immutable request objects so handlers don’t accidentally modify shared state
  • Consider order carefully — handlers that short-circuit (auth, rate limiting) should typically come first

Common Mistakes

  • Creating circular chains where a handler eventually calls itself, causing infinite loops
  • Forgetting to call the next handler, silently dropping requests that should have been processed
  • Putting slow or blocking handlers early in the chain, causing unnecessary latency for rejected requests
  • Storing mutable state in handlers that are reused across requests, causing cross-request contamination
  • Building overly long chains that become hard to debug and reason about
  • Not providing a default handler at the end of the chain, leaving requests unhandled
  • Mixing concerns within a single handler instead of keeping them focused
  • Not documenting handler dependencies and expected order
  • Failing to handle exceptions in handlers, causing the entire chain to fail
  • Using the chain pattern when a simple conditional would suffice

Advanced Techniques

Chain with Context Object

Pass a context object through the chain to accumulate state and metadata:

from abc import ABC, abstractmethod
from typing import Optional, Dict, Any

class RequestContext:
    def __init__(self, request: str):
        self.request = request
        self.metadata: Dict[str, Any] = {}
        self.response: Optional[str] = None
        self.handled = False

class Handler(ABC):
    def __init__(self):
        self._next: Optional['Handler'] = None

    def set_next(self, handler: 'Handler') -> 'Handler':
        self._next = handler
        return handler

    @abstractmethod
    def handle(self, context: RequestContext) -> None:
        pass

    def _pass_to_next(self, context: RequestContext) -> None:
        if self._next and not context.handled:
            self._next.handle(context)

class LoggingHandler(Handler):
    def handle(self, context: RequestContext) -> None:
        context.metadata['logged_at'] = 'handler1'
        print(f"Logging: {context.request}")
        self._pass_to_next(context)

class AuthHandler(Handler):
    def handle(self, context: RequestContext) -> None:
        if not context.request.startswith("token:"):
            context.response = "401 Unauthorized"
            context.handled = True
            return
        context.metadata['authenticated'] = True
        self._pass_to_next(context)

class DataHandler(Handler):
    def handle(self, context: RequestContext) -> None:
        context.response = f"Processed: {context.request}"
        context.handled = True

# Usage
context = RequestContext("token:abc123")
handler = LoggingHandler()
handler.set_next(AuthHandler()).set_next(DataHandler())
handler.handle(context)

print(f"Response: {context.response}")
print(f"Metadata: {context.metadata}")

Chain with Result Aggregation

Collect results from multiple handlers instead of stopping at the first match:

import java.util.ArrayList;
import java.util.List;

public interface Handler {
    void handle(Request request, List<Result> results);
}

public class Request {
    private String data;
    
    public Request(String data) {
        this.data = data;
    }
    
    public String getData() {
        return data;
    }
}

public class Result {
    private String handlerName;
    private String value;
    
    public Result(String handlerName, String value) {
        this.handlerName = handlerName;
        this.value = value;
    }
    
    public String getHandlerName() { return handlerName; }
    public String getValue() { return value; }
}

public class ValidationHandler implements Handler {
    private String name;
    
    public ValidationHandler(String name) {
        this.name = name;
    }
    
    @Override
    public void handle(Request request, List<Result> results) {
        if (request.getData().length() > 10) {
            results.add(new Result(name, "FAIL: Too long"));
        } else {
            results.add(new Result(name, "PASS"));
        }
    }
}

public class SecurityHandler implements Handler {
    private String name;
    
    public SecurityHandler(String name) {
        this.name = name;
    }
    
    @Override
    public void handle(Request request, List<Result> results) {
        if (request.getData().contains("<script>")) {
            results.add(new Result(name, "FAIL: XSS detected"));
        } else {
            results.add(new Result(name, "PASS"));
        }
    }
}

public class Chain {
    private List<Handler> handlers = new ArrayList<>();
    
    public void addHandler(Handler handler) {
        handlers.add(handler);
    }
    
    public List<Result> execute(Request request) {
        List<Result> results = new ArrayList<>();
        for (Handler handler : handlers) {
            handler.handle(request, results);
        }
        return results;
    }
}

// Usage
Chain chain = new Chain();
chain.addHandler(new ValidationHandler("LengthValidator"));
chain.addHandler(new SecurityHandler("XSSChecker"));

Request request = new Request("safe input");
List<Result> results = chain.execute(request);

for (Result result : results) {
    System.out.println(result.getHandlerName() + ": " + result.getValue());
}

Chain with Conditional Branching

Support branching based on request characteristics:

class Handler {
  constructor() {
    this.nextHandler = null;
    this.branchHandlers = new Map();
  }

  setNext(handler) {
    this.nextHandler = handler;
    return handler;
  }

  addBranch(condition, handler) {
    this.branchHandlers.set(condition, handler);
    return this;
  }

  handle(request) {
    // Check branches first
    for (const [condition, handler] of this.branchHandlers.entries()) {
      if (condition(request)) {
        return handler.handle(request);
      }
    }
    
    // Fall through to next handler
    if (this.nextHandler) {
      return this.nextHandler.handle(request);
    }
    return null;
  }
}

class RouteHandler extends Handler {
  constructor(route) {
    super();
    this.route = route;
  }

  handle(request) {
    if (request.path === this.route) {
      return `Handled route: ${this.route}`;
    }
    return super.handle(request);
  }
}

// Usage with branching
const handler = new Handler();
handler
  .addBranch(req => req.method === 'GET', new RouteHandler('/get'))
  .addBranch(req => req.method === 'POST', new RouteHandler('/post'))
  .setNext(new RouteHandler('/default'));

console.log(handler.handle({ method: 'GET', path: '/get' })); // Handled route: /get
console.log(handler.handle({ method: 'POST', path: '/post' })); // Handled route: /post
console.log(handler.handle({ method: 'DELETE', path: '/delete' })); // Handled route: /default

Chain with Retry Logic

Add retry capabilities to handlers for transient failures:

from abc import ABC, abstractmethod
from typing import Optional
import time

class Handler(ABC):
    def __init__(self):
        self._next: Optional['Handler'] = None
        self.max_retries = 0
        self.retry_delay = 0

    def set_next(self, handler: 'Handler') -> 'Handler':
        self._next = handler
        return handler

    def with_retry(self, max_retries: int, delay: float = 1.0) -> 'Handler':
        self.max_retries = max_retries
        self.retry_delay = delay
        return self

    def handle(self, request: str) -> Optional[str]:
        for attempt in range(self.max_retries + 1):
            try:
                result = self._handle_impl(request)
                if result is not None:
                    return result
            except Exception as e:
                if attempt == self.max_retries:
                    raise
                time.sleep(self.retry_delay)
        return self._pass_to_next(request)

    @abstractmethod
    def _handle_impl(self, request: str) -> Optional[str]:
        pass

    def _pass_to_next(self, request: str) -> Optional[str]:
        if self._next:
            return self._next.handle(request)
        return None

class DatabaseHandler(Handler):
    def _handle_impl(self, request: str) -> Optional[str]:
        # Simulate transient failure
        if "fail" in request:
            raise ConnectionError("Database connection failed")
        return f"DB: {request}"

class CacheHandler(Handler):
    def _handle_impl(self, request: str) -> Optional[str]:
        if "cached" in request:
            return f"Cache: {request}"
        return None

# Usage with retry
handler = CacheHandler()
handler.set_next(DatabaseHandler().with_retry(max_retries=3, delay=0.5))

print(handler.handle("cached_data"))  # Cache: cached_data
print(handler.handle("normal_data"))  # DB: normal_data
print(handler.handle("fail_data"))    # Retries 3 times then raises

Chain with Async/Await

Support asynchronous request processing:

class AsyncHandler {
  constructor() {
    this.nextHandler = null;
  }

  setNext(handler) {
    this.nextHandler = handler;
    return handler;
  }

  async handle(request) {
    const result = await this.process(request);
    if (result !== null) {
      return result;
    }
    if (this.nextHandler) {
      return await this.nextHandler.handle(request);
    }
    return null;
  }

  async process(request) {
    return null; // Override in subclasses
  }
}

class AsyncAuthHandler extends AsyncHandler {
  async process(request) {
    // Simulate async auth check
    await new Promise(resolve => setTimeout(resolve, 100));
    if (!request.startsWith("token:")) {
      return "401 Unauthorized";
    }
    return null;
  }
}

class AsyncDataHandler extends AsyncHandler {
  async process(request) {
    // Simulate async data fetch
    await new Promise(resolve => setTimeout(resolve, 50));
    return `Processed: ${request}`;
  }
}

// Usage
async function main() {
  const handler = new AsyncAuthHandler();
  handler.setNext(new AsyncDataHandler());

  console.log(await handler.handle("token:abc123")); // Processed
  console.log(await handler.handle("bad-request"));    // 401
}

main();

Chain with Middleware Pattern

Implement a middleware-style chain with explicit next() calls:

from typing import Callable, Any

def middleware(handler: Callable[[Any], Any]) -> Callable[[Any], Any]:
    def wrapper(request: Any) -> Any:
        print(f"Before: {request}")
        result = handler(request)
        print(f"After: {result}")
        return result
    return wrapper

def auth_middleware(next_handler: Callable) -> Callable:
    def handler(request: dict) -> Any:
        if not request.get('token'):
            return {'error': 'Unauthorized'}
        return next_handler(request)
    return handler

def rate_limit_middleware(next_handler: Callable) -> Callable:
    counter = {'count': 0}
    def handler(request: dict) -> Any:
        counter['count'] += 1
        if counter['count'] > 5:
            return {'error': 'Rate limited'}
        return next_handler(request)
    return handler

def data_handler(request: dict) -> dict:
    return {'data': f"Processed {request['token']}"}

# Build middleware chain
def build_chain():
    return rate_limit_middleware(auth_middleware(data_handler))

# Usage
chain = build_chain()
print(chain({'token': 'abc123'}))  # Works
print(chain({}))                    # Unauthorized

Best Practices

  1. Keep handlers single-responsibility. Each handler should handle one specific concern (auth, validation, logging, etc.) to maintain clarity and testability.

  2. Provide a default handler. Always include a catch-all handler at the end of the chain to handle requests that fall through, preventing silent failures.

  3. Document handler order. Clearly document the expected order of handlers and any dependencies between them, as order considerably affects behavior.

  4. Use immutable request objects. Pass immutable request objects through the chain to prevent handlers from accidentally modifying shared state.

  5. Handle exceptions gracefully. Each handler should catch and handle its own exceptions, or wrap them appropriately to prevent chain failure.

  6. Consider performance impact. Place fast, short-circuiting handlers (auth, rate limiting) early in the chain to fail fast and avoid unnecessary processing.

  7. Support chain reconfiguration. Allow handlers to be added, removed, or reordered at runtime for flexibility.

  8. Add logging and monitoring. Include logging handlers to trace request flow through the chain and identify bottlenecks or failures.

  9. Avoid circular references. Ensure the chain structure is acyclic to prevent infinite loops during request processing.

  10. Test handlers in isolation. Write unit tests for each handler independently, then integration tests for the complete chain.

Frequently Asked Questions

Q: Is this the same as middleware in web frameworks? A: Yes. Express.js middleware, Django middleware, and ASP.NET Core middleware are all implementations of the Chain of Responsibility Pattern. Each middleware decides whether to process the request, pass it along, or short-circuit with a response.

Q: What happens if no handler processes the request? A: By default, the request falls through the chain unhandled. Consider adding a Decorator for enrichment or a default handler for catch-all behavior. You should add a catch-all handler at the end that returns a default response or throws an appropriate error.

Q: Can handlers modify the request before passing it along? A: Yes. Unlike a pure pass-or-fail chain, handlers can transform, enrich, or validate the request before forwarding it. This is common in middleware pipelines.

Q: How do I handle async operations in a chain? A: Use async/await patterns where each handler returns a promise. The chain awaits each handler’s completion before passing to the next. This is essential for I/O-bound operations like database queries or API calls.

Q: Should I use this pattern for event handling? A: Yes. Event systems often use a variation of this pattern where multiple event listeners (handlers) can process an event. Unlike a linear chain, event systems typically broadcast to all registered handlers.

Q: How do I add logging to trace request flow? A: Add a logging handler that records the request before and after each handler. Include timestamps and handler names to trace the execution path and identify performance bottlenecks.

Q: Can handlers have side effects? A: Yes, handlers can perform side effects like logging, metrics collection, or database updates. However, keep side effects focused and document them clearly to avoid unexpected behavior.

Q: How do I handle timeout scenarios in a chain? A: Implement timeout middleware that tracks request duration and short-circuits if processing exceeds a threshold. This prevents slow handlers from blocking the entire chain indefinitely.

Q: Should handlers be stateless? A: Ideally yes. Stateless handlers are easier to test and reuse. If state is necessary, ensure it’s request-scoped (stored in the context object) rather than handler-scoped to avoid cross-request contamination.

Q: How do I implement circuit breaking in a chain? A: Add a circuit breaker handler that tracks failure rates and short-circuits requests when a downstream service is failing. This prevents cascading failures and improves system resilience.

Q: Can I use this pattern for validation pipelines? A: Yes. Validation chains are a common use case where each handler checks a different aspect (format, business rules, security constraints). Results can be aggregated to provide detailed validation feedback.

Q: How do I handle priority in handler execution? A: Implement priority-based handler ordering where handlers with higher priority execute first. This is useful for ensuring critical checks (auth, security) run before less critical operations.

Q: Should I use dependency injection with handlers? A: Yes. Handlers often require dependencies (database connections, external services, configuration). Use dependency injection to provide these dependencies, making handlers testable and flexible.

Q: How do I implement request cancellation? A: Add cancellation support by including a cancellation token in the request context. Handlers should check the token periodically and abort processing if cancellation is requested.

Q: Can chains be nested or hierarchical? A: Yes. You can create hierarchical chains where a handler itself contains a sub-chain. This is useful for organizing complex processing logic into manageable units.

Q: How do I add metrics collection to a chain? A: Include a metrics handler that records timing, success/failure rates, and throughput for each handler. This data is valuable for monitoring and optimizing chain performance.

Q: Should I use this pattern for data transformation pipelines? A: Yes. Transformation chains where each handler applies a specific transformation (parsing, enrichment, normalization) are a common and effective use case.

Q: How do I handle version compatibility in handlers? A: Implement version-aware handlers that can process different request versions. Include version information in the request context and route to appropriate handler logic based on version.

Q: Can handlers be dynamically added or removed at runtime? A: Yes. Implement a chain manager that allows handlers to be added, removed, or reordered dynamically. This enables runtime reconfiguration without restarting the application.

Q: How do I implement request replay for debugging? A: Add a replay handler that logs complete request context and responses. Store this information in a way that allows replaying requests through the chain for debugging and testing.

Q: Should I use this pattern for API gateway routing? A: Yes. API gateways often use chain of responsibility for request routing, where each handler checks routing rules (path, headers, query parameters) and directs requests to appropriate backend services.

Q: How do I handle request validation vs business logic separation? A: Separate validation handlers (format, type checking) from business logic handlers (domain rules, permissions). Place validation early in the chain to fail fast on invalid requests.

Q: Can chains be parallelized for performance? A: Traditional chains are sequential, but you can implement parallel chains where independent handlers execute concurrently and results are aggregated. This is useful for validation or enrichment operations that don’t depend on each other.

Q: How do I implement request context propagation? A: Use a context object that travels through the chain, accumulating metadata, logs, and intermediate results. This context provides visibility into the request’s journey through the handlers.

Q: Should I use this pattern for file processing pipelines? A: Yes. File processing chains where each handler performs a specific operation (validation, transformation, compression, upload) are a natural fit for this pattern.

Q: How do I handle error recovery in a chain? A: Implement error handling strategies at the handler level (retry, fallback, circuit breaker) and chain level (catch-all error handler, graceful degradation). Document recovery behavior clearly.

Q: Can handlers communicate with each other? A: Handlers can communicate through the shared context object, but avoid direct dependencies between handlers. This maintains loose coupling and allows handlers to be reordered or replaced independently.

Q: How do I implement request throttling in a chain? A: Add a throttling handler that tracks request rates and short-circuits when limits are exceeded. Implement different throttling strategies (rate limiting, concurrency limiting, queueing) based on your requirements.

Q: Should I use this pattern for message processing in queues? A: Yes. Message queue consumers often use chain of responsibility to process messages through multiple stages (validation, transformation, routing, persistence) before final handling.

Q: How do I add conditional handler execution? A: Implement conditional logic in handlers or use a branching handler that routes requests to different sub-chains based on request characteristics (user type, request type, metadata).

Q: Can chains be composed from smaller chains? A: Yes. Implement chain composition where smaller, focused chains can be combined into larger chains. This promotes reusability and modular design.

Q: How do I implement request tracing across distributed systems? A: Include distributed tracing context (trace ID, span ID) in the request object. Propagate this context through the chain and to external service calls for end-to-end tracing.

Q: Should I use this pattern for workflow orchestration? A: Yes. Workflow engines often use chain-like patterns where each step in a workflow is a handler that processes the workflow state and decides whether to continue or stop.

Q: How do I handle request size limits in a chain? A: Add a size validation handler that checks request size early in the chain and rejects oversized requests. This prevents processing of requests that would fail later due to size constraints.

Q: Can handlers be implemented as functions instead of classes? A: Yes. Functional handlers are simpler and more composable in functional programming paradigms. Use higher-order functions to chain handlers together instead of class-based inheritance.

Q: How do I implement request sanitization in a chain? A: Add sanitization handlers that clean or normalize request data (trim whitespace, remove special characters, normalize case). Place these early to ensure all downstream handlers work with clean data.

Q: Should I use this pattern for permission checking? A: Yes. Permission chains where each handler checks specific permissions (read, write, admin) are effective for complex authorization scenarios with multiple permission types.

Q: How do I add request enrichment in a chain? A: Implement enrichment handlers that add metadata, computed fields, or related data to the request context. This is useful for providing downstream handlers with additional context without requiring them to fetch it.

Q: Can chains be used for A/B testing or feature flags? A: Yes. Add handlers that check feature flags or A/B test configurations and route requests to different processing paths or return different responses based on the configuration.

Q: How do I implement request deduplication in a chain? A: Add a deduplication handler that checks if a request has been processed recently (using a cache or idempotency key) and returns the cached result if found, preventing duplicate processing.

Q: Should I use this pattern for data validation in forms? A: Yes. Form validation chains where each handler validates a specific field or rule (required fields, format validation, business rules) provide structured, reusable validation logic.

Q: How do I handle request transformation vs validation separation? A: Separate transformation handlers (modify request data) from validation handlers (check request data). Place validation before transformation to ensure only valid data is transformed.

Q: Can handlers be stateful for rate limiting? A: Yes, but be careful. Stateful handlers like rate limiters need to manage their state carefully (thread-safe access, proper cleanup, state reset). Consider using external stores (Redis) for state to improve scalability.

Q: How do I implement request timeout per handler? A: Add timeout logic to each handler or use a timeout wrapper that monitors handler execution time. This prevents slow handlers from blocking the entire chain indefinitely.

Q: Should I use this pattern for cache lookup chains? A: Yes. Cache chains where each handler checks a different cache level (L1 memory cache, L2 distributed cache, L3 database) are effective for multi-tier caching strategies.

Q: How do I add request logging for audit trails? A: Include an audit logging handler that records request details, handler execution, and results. Store this information securely for compliance and debugging purposes.

Q: Can chains be used for request routing based on content? A: Yes. Content-based routing handlers examine request content (headers, body, parameters) and route to different sub-chains or backends based on routing rules.

Q: How do I implement request versioning in a chain? A: Include version information in the request and implement version-aware handlers that can process different request formats or apply different logic based on version.

Q: Should I use this pattern for data enrichment from external APIs? A: Yes. Enrichment chains where each handler fetches additional data from different external APIs and adds it to the request context are a common use case.

Q: How do I handle request context isolation in multi-tenant systems? A: Include tenant identification in the request context and ensure handlers respect tenant isolation (separate data access, per-tenant configuration, resource quotas).

Q: Can handlers be implemented as middleware in web frameworks? A: Yes. Most web frameworks (Express, Django, ASP.NET Core) support middleware patterns that are essentially chain of responsibility implementations. use framework-specific middleware APIs.

Q: How do I add request compression/decompression in a chain? A: Add compression/decompression handlers that handle content encoding (gzip, deflate, brotli). Place decompression early and compression late in the chain.

Q: Should I use this pattern for request preprocessing? A: Yes. Preprocessing chains where each handler performs a specific preprocessing step (parsing, normalization, enrichment) prepare requests for main processing logic.

Q: How do I implement request context timeout? A: Add a timeout handler that tracks overall request processing time and short-circuits if the total time exceeds a threshold, preventing long-running requests from consuming resources.

Q: Can chains be used for request post-processing? A: Yes. Post-processing chains where each handler performs operations after main processing (response formatting, logging, cleanup, metrics) are effective for response handling.

Q: How do I add request signature verification in a chain? A: Include a signature verification handler that checks request signatures (HMAC, JWT) to ensure request authenticity and integrity. Place this early in the chain for security.

Q: Should I use this pattern for request retry logic? A: Yes. Retry handlers can implement exponential backoff, circuit breaking, and dead letter queueing for failed requests. Combine with idempotency for safe retries.

Q: How do I implement request context cleanup in a chain? A: Add a cleanup handler at the end of the chain that releases resources, closes connections, and performs other cleanup operations. Ensure this runs even if earlier handlers fail.

Q: Can handlers be dynamically selected based on configuration? A: Yes. Implement a handler registry and configuration-driven chain builder that selects and orders handlers based on configuration files or environment variables.

Q: How do I add request context propagation across service boundaries? A: Include correlation IDs, trace IDs, and other context metadata in requests when calling external services. This enables distributed tracing and debugging across service boundaries.

Q: Should I use this pattern for request aggregation? A: Yes. Aggregation chains where each handler collects data from different sources and combines it into a unified response are effective for data aggregation scenarios.

Q: How do I implement request context validation in a chain? A: Add context validation handlers that verify the request context is complete and valid (required fields present, data types correct, constraints satisfied) before processing.

Q: Can chains be used for request transformation for different formats? A: Yes. Transformation chains where each handler converts between formats (JSON to XML, CSV to JSON, protocol buffers to JSON) are useful for format conversion scenarios.

Q: How do I add request context enrichment from databases? A: Implement enrichment handlers that fetch related data from databases and add it to the request context. Use connection pooling and caching to optimize performance.

Q: Should I use this pattern for request context security checks? A: Yes. Security chains where each handler performs a specific security check (authentication, authorization, input validation, output encoding) provide defense in depth.

Q: How do I implement request context monitoring in a chain? A: Add monitoring handlers that collect metrics (latency, throughput, error rates) and health checks for each handler. Use this data for observability and alerting.

Q: Can handlers be implemented as plugins? A: Yes. Implement a plugin system where handlers can be dynamically loaded and registered with the chain. This enables extensibility without modifying core code.

Q: How do I add request context serialization in a chain? A: Include serialization handlers that convert request context to different formats (JSON, XML, binary) for storage, transmission, or logging purposes.

Q: Should I use this pattern for request context deserialization? A: Yes. Deserialization chains where each handler parses and validates different parts of a serialized request are effective for handling complex request formats.

Q: How do I implement request context filtering in a chain? A: Add filtering handlers that remove or mask sensitive data from the request context (passwords, tokens, PII) before logging or passing to certain handlers.

Q: Can chains be used for request context routing to different handlers? A: Yes. Routing handlers examine request characteristics and route to different sub-chains or handler sets based on routing rules (content type, user role, geographic location).

Q: How do I add request context normalization in a chain? A: Implement normalization handlers that standardize request data (case normalization, whitespace trimming, date format conversion) to ensure consistent processing downstream.

Q: Should I use this pattern for request context validation against schemas? A: Yes. Schema validation chains where each handler validates against different schemas (JSON Schema, XML Schema, custom schemas) ensure request data conforms to expected structure.

Q: How do I implement request context transformation for legacy systems? A: Add transformation handlers that convert modern request formats to legacy formats (or vice versa) for compatibility with legacy systems or APIs.

Q: Can handlers be implemented as lambda functions in cloud platforms? A: Yes. Cloud platforms (AWS Lambda, Azure Functions) support serverless handlers that can be chained together using event-driven architectures or orchestration services.

Q: How do I add request context encryption/decryption in a chain? A: Include encryption/decryption handlers that protect sensitive data in the request context. Place decryption early and encryption late in the chain.

Q: Should I use this pattern for request context compression for network transmission? A: Yes. Compression handlers that compress request data before transmission and decompress after receipt reduce bandwidth usage and improve performance.

Q: How do I implement request context validation against business rules? A: Add business rule validation handlers that check domain-specific constraints (inventory availability, user permissions, business logic) to ensure requests are valid for the business context.

Q: Can chains be used for request context aggregation from multiple sources? A: Yes. Aggregation chains where each handler fetches data from different sources (databases, APIs, caches) and combines it into a unified response are effective for data aggregation.

Q: How do I add request context deduplication for idempotent operations? A: Implement deduplication handlers that check for duplicate requests using idempotency keys and return cached results to prevent duplicate processing.

Q: Should I use this pattern for request context transformation for API compatibility? A: Yes. Transformation chains that convert between different API versions or formats ensure compatibility when integrating with multiple API versions or external systems.

Q: How do I implement request context validation for security compliance? A: Add security compliance handlers that check requests against security policies (input validation, output encoding, security headers) to ensure compliance with security standards.

Q: Can handlers be implemented as message queue consumers? A: Yes. Message queue consumers often implement chain of responsibility to process messages through multiple stages (validation, transformation, routing, persistence).

Q: How do I add request context enrichment from external services? A: Implement enrichment handlers that call external services (REST APIs, GraphQL, gRPC) to fetch additional data and add it to the request context.

Q: Should I use this pattern for request context validation for data quality? A: Yes. Data quality validation chains where each handler checks different quality aspects (completeness, accuracy, consistency, timeliness) ensure high-quality data processing.

Q: How do I implement request context transformation for data migration? A: Add transformation handlers that convert data from legacy formats to new formats as part of data migration projects, ensuring smooth transition between systems.

Q: Can chains be used for request context routing in microservices? A: Yes. API gateways in microservices architectures use chain of responsibility for request routing, where each handler checks routing rules and directs requests to appropriate services.

Q: How do I add request context validation for regulatory compliance? A: Implement compliance validation handlers that check requests against regulatory requirements (GDPR, HIPAA, PCI-DSS) to ensure compliance with applicable regulations.

Q: Should I use this pattern for request context transformation for analytics? A: Yes. Transformation chains that prepare request data for analytics (aggregation, filtering, enrichment) are effective for data pipeline processing.

Q: How do I implement request context validation for performance optimization? A: Add performance validation handlers that check request characteristics (size, complexity, resource requirements) and optimize or reject requests to maintain system performance.

Q: Can handlers be implemented as workflow steps in business process automation? A: Yes. Business process automation tools often use chain-like patterns where each step in a workflow is a handler that processes the workflow state.

Q: How do I add request context enrichment from user profiles? A: Implement enrichment handlers that fetch user profile data (preferences, settings, history) and add it to the request context for personalized processing.

Q: Should I use this pattern for request context validation for data integrity? A: Yes. Data integrity validation chains where each handler checks different integrity aspects (checksums, hashes, referential integrity) ensure data consistency and reliability.

Q: How do I implement request context transformation for internationalization? A: Add transformation handlers that handle internationalization (i18n) concerns (locale detection, currency conversion, date/time formatting) for global applications.

Q: Can chains be used for request context validation in real-time systems? A: Yes. Real-time systems use chain of responsibility for request validation and processing where low latency is critical, with fast-failing handlers to minimize processing time.

Q: How do I add request context enrichment from configuration? A: Implement enrichment handlers that load configuration data (feature flags, settings, policies) and add it to the request context for dynamic behavior.

Q: Should I use this pattern for request context validation for data governance? A: Yes. Data governance validation chains where each handler checks governance policies (data classification, retention policies, access policies) ensure compliance with data governance standards.

Q: How do I implement request context transformation for machine learning? A: Add transformation handlers that prepare request data for machine learning models (feature extraction, normalization, encoding) for ML inference pipelines.

Q: Can handlers be implemented as stream processors in data streaming? A: Yes. Data streaming platforms (Kafka, Kinesis) use chain-like patterns where each processor in the stream performs operations on the data.

Q: How do I add request context enrichment from geolocation data? A: Implement enrichment handlers that fetch geolocation data (IP geolocation, GPS coordinates) and add it to the request context for location-based processing.

Q: Should I use this pattern for request context validation for data privacy? A: Yes. Data privacy validation chains where each handler checks privacy policies (consent, data minimization, purpose limitation) ensure compliance with privacy regulations.

Q: How do I implement request context transformation for legacy data formats? A: Add transformation handlers that convert legacy data formats (COBOL copybooks, fixed-width files) to modern formats (JSON, XML, CSV) for integration with modern systems.

Q: Can chains be used for request context validation in high-throughput systems? A: Yes. High-throughput systems use chain of responsibility with optimized handlers (async processing, connection pooling, caching) to handle large request volumes efficiently.

Q: How do I add request context enrichment from session data? A: Implement enrichment handlers that fetch session data (user session, shopping cart, preferences) and add it to the request context for session-aware processing.

Q: Should I use this pattern for request context validation for data lineage? A: Yes. Data lineage validation chains where each handler tracks data provenance and transformations ensure data lineage and auditability.

Q: How do I implement request context transformation for API versioning? A: Add transformation handlers that convert between different API versions (v1 to v2, v2 to v3) to maintain backward compatibility while evolving APIs.

Q: Can handlers be implemented as ETL pipeline steps? A: Yes. ETL (Extract, Transform, Load) pipelines use chain of responsibility where each step performs extraction, transformation, or loading operations on data.

Q: How do I add request context enrichment from device information? A: Implement enrichment handlers that fetch device information (user agent, device type, screen resolution) and add it to the request context for device-aware processing.

Q: Should I use this pattern for request context validation for data consistency? A: Yes. Data consistency validation chains where each handler checks consistency across data sources (master data, transactional data) ensure data consistency and accuracy.

Q: How do I implement request context transformation for protocol conversion? A: Add transformation handlers that convert between different protocols (HTTP to gRPC, REST to GraphQL, SOAP to REST) for protocol compatibility in distributed systems.

Q: Can chains be used for request context validation in safety-critical systems? A: Yes. Safety-critical systems use chain of responsibility with rigorous validation handlers to ensure safety and reliability, often with formal verification and redundancy.

Q: How do I add request context enrichment from social media data? A: Implement enrichment handlers that fetch social media data (user profiles, social graphs, content) and add it to the request context for social-aware applications.

Q: Should I use this pattern for request context validation for data synchronization? A: Yes. Data synchronization validation chains where each handler checks synchronization status across systems ensure data consistency and timely updates.

Q: How do I implement request context transformation for data serialization? A: Add transformation handlers that serialize data to different formats (JSON, XML, Protocol Buffers, Avro) for storage, transmission, or processing in different systems.

Q: Can handlers be implemented as CI/CD pipeline steps? A: Yes. CI/CD pipelines use chain of responsibility where each step performs build, test, or deployment operations, with the ability to fail fast and stop the pipeline.

Q: How do I add request context enrichment from business intelligence data? A: Implement enrichment handlers that fetch BI data (metrics, KPIs, reports) and add it to the request context for business intelligence applications.

Q: Should I use this pattern for request context validation for data archiving? A: Yes. Data archiving validation chains where each handler checks archiving policies (retention periods, access controls, compression) ensure proper data archiving.

Q: How do I implement request context transformation for data anonymization? A: Add transformation handlers that anonymize sensitive data (masking, hashing, tokenization) for privacy compliance while preserving data utility.

Q: Can chains be used for request context validation in financial systems? A: Yes. Financial systems use chain of responsibility with validation handlers for regulatory compliance (Sarbanes-Oxley, Basel III, PCI-DSS) and financial controls.

Q: How do I add request context enrichment from IoT device data? A: Implement enrichment handlers that fetch IoT device data (sensor readings, device status, telemetry) and add it to the request context for IoT applications.

Q: Should I use this pattern for request context validation for data backup? A: Yes. Data backup validation chains where each handler checks backup policies (frequency, retention, integrity) ensure reliable data backup and recovery.

Q: How do I implement request context transformation for data parsing? A: Add transformation handlers that parse different data formats (CSV, JSON, XML, YAML, INI) into structured data for processing by downstream handlers.

Q: Can handlers be implemented as bot processing steps? A: Yes. Chatbots and automation bots use chain of responsibility where each handler processes user input, performs intent recognition, and generates responses.

Q: How do I add request context enrichment from CRM data? A: Implement enrichment handlers that fetch CRM data (customer profiles, interaction history, sales data) and add it to the request context for CRM-integrated applications.

Q: Should I use this pattern for request context validation for data migration? A: Yes. Data migration validation chains where each handler validates migrated data (completeness, accuracy, consistency) ensure successful data migration.

Q: How do I implement request context transformation for data formatting? A: Add transformation handlers that format data (date formatting, number formatting, currency formatting) for display or processing in different locales or systems.

Q: Can chains be used for request context validation in healthcare systems? A: Yes. Healthcare systems use chain of responsibility with validation handlers for regulatory compliance (HIPAA, HL7, FHIR) and patient data protection.

Q: How do I add request context enrichment from marketing data? A: Implement enrichment handlers that fetch marketing data (campaign data, attribution, conversion tracking) and add it to the request context for marketing applications.

Q: Should I use this pattern for request context validation for data replication? A: Yes. Data replication validation chains where each handler checks replication status and consistency across systems ensure data replication reliability.

Q: How do I implement request context transformation for data encoding? A: Add transformation handlers that encode data (Base64, URL encoding, HTML encoding) for safe transmission or storage in different contexts.

Q: Can handlers be implemented as game processing steps? A: Yes. Game engines use chain of responsibility where each handler processes game state (input handling, physics simulation, rendering, AI) in a game loop.

Q: How do I add request context enrichment from search data? A: Implement enrichment handlers that fetch search data (search results, relevance scores, query analysis) and add it to the request context for search-integrated applications.

Q: Should I use this pattern for request context validation for data sharding? A: Yes. Data sharding validation chains where each handler validates sharding rules and ensures data is routed to the correct shard for distributed data systems.

Q: How do I implement request context transformation for data aggregation? A: Add transformation handlers that aggregate data from multiple sources (sum, average, count, group by) for reporting and analytics applications.

Q: Can chains be used for request context validation in telecommunications? A: Yes. Telecommunications systems use chain of responsibility for call processing, where each handler performs validation, routing, and billing operations.

Q: How do I add request context enrichment from logistics data? A: Implement enrichment handlers that fetch logistics data (tracking information, inventory status, delivery estimates) and add it to the request context for logistics applications.

Q: Should I use this pattern for request context validation for data partitioning? A: Yes. Data partitioning validation chains where each handler validates partitioning rules and ensures data is correctly partitioned for distributed processing.

Q: How do I implement request context transformation for data normalization? A: Add transformation handlers that normalize data (standardizing formats, removing duplicates, resolving inconsistencies) for consistent processing across systems.

Q: Can handlers be implemented as robotics processing steps? A: Yes. Robotics systems use chain of responsibility where each handler processes sensor data, performs control logic, and generates actuator commands.

Q: How do I add request context enrichment from weather data? A: Implement enrichment handlers that fetch weather data (current conditions, forecasts, alerts) and add it to the request context for weather-aware applications.

Q: Should I use this pattern for request context validation for data indexing? A: Yes. Data indexing validation chains where each handler validates data quality and structure before indexing ensure high-quality search indexes.

Q: How do I implement request context transformation for data deduplication? A: Add transformation handlers that identify and remove duplicate data based on various criteria (exact match, fuzzy match, semantic similarity) for data deduplication.

Q: Can chains be used for request context validation in e-commerce? A: Yes. E-commerce systems use chain of responsibility for order processing, where each handler validates inventory, applies discounts, and processes payments.

Q: How do I add request context enrichment from social graph data? A: Implement enrichment handlers that fetch social graph data (connections, relationships, influence metrics) and add it to the request context for social network applications.

Q: Should I use this pattern for request context validation for data purging? A: Yes. Data purging validation chains where each handler validates purging policies (retention expiration, legal holds, compliance) ensure proper data deletion.

Q: How do I implement request context transformation for data masking? A: Add transformation handlers that mask sensitive data (partial masking, full masking, format-preserving encryption) for privacy protection while maintaining data utility.

Q: Can handlers be implemented as smart contract execution steps? A: Yes. Blockchain systems use chain of responsibility where each handler validates transactions, executes smart contract logic, and updates blockchain state.

Q: How do I add request context enrichment from recommendation data? A: Implement enrichment handlers that fetch recommendation data (personalized recommendations, collaborative filtering, content-based filtering) and add it to the request context for recommendation systems.

Q: Should I use this pattern for request context validation for data versioning? A: Yes. Data versioning validation chains where each handler validates version compatibility and ensures data schema compatibility across versions.

Q: How do I implement request context transformation for data conversion? A: Add transformation handlers that convert data between different types (string to number, date to timestamp, binary to base64) for type compatibility across systems.

Q: Can chains be used for request context validation in government systems? A: Yes. Government systems use chain of responsibility with validation handlers for regulatory compliance (FOIA, accessibility, security) and government-specific requirements.

Q: How do I add request context enrichment from streaming data? A: Implement enrichment handlers that fetch streaming data (live feeds, real-time updates, event streams) and add it to the request context for real-time applications.

Q: Should I use this pattern for request context validation for data quality monitoring? A: Yes. Data quality monitoring chains where each handler monitors different quality dimensions (accuracy, completeness, timeliness) and triggers alerts for quality issues.

Q: How do I implement request context transformation for data parsing? A: Add transformation handlers that parse complex data structures (nested JSON, XML documents, binary formats) into structured objects for easier processing.

Q: Can handlers be implemented as edge computing processing steps? A: Yes. Edge computing systems use chain of responsibility where each handler processes data at the edge (validation, filtering, aggregation) before sending to central systems.

Q: How do I add request context enrichment from blockchain data? A: Implement enrichment handlers that fetch blockchain data (transaction history, smart contract state, NFT metadata) and add it to the request context for blockchain-integrated applications.

Q: Should I use this pattern for request context validation for data governance? A: Yes. Data governance validation chains where each handler validates governance policies (access control, data classification, lineage tracking) ensure compliance with governance frameworks.

Q: How do I implement request context transformation for data validation? A: Add transformation handlers that validate data against schemas, rules, and constraints to ensure data quality and consistency before processing.

Q: Can chains be used for request context validation in embedded systems? A: Yes. Embedded systems use chain of responsibility for sensor data processing, where each handler filters, validates, and processes sensor readings.

Q: How do I add request context enrichment from satellite data? A: Implement enrichment handlers that fetch satellite data (imagery, telemetry, positioning) and add it to the request context for satellite-based applications.

Q: Should I use this pattern for request context validation for data lifecycle management? A: Yes. Data lifecycle management chains where each handler validates lifecycle policies (creation, usage, archival, deletion) ensure proper data lifecycle management.

Q: How do I implement request context transformation for data integration? A: Add transformation handlers that integrate data from multiple sources (merge, join, union) for unified data processing and analysis.

Q: Can handlers be implemented as quantum computing processing steps? A: Yes. Quantum computing systems use chain of responsibility where each handler prepares quantum states, executes quantum operations, and measures results.

Q: How do I add request context enrichment from biometric data? A: Implement enrichment handlers that fetch biometric data (fingerprints, facial recognition, voice patterns) and add it to the request context for biometric authentication applications.

Q: Should I use this pattern for request context validation for data provenance? A: Yes. Data provenance validation chains where each handler tracks data origin, transformations, and ownership ensure data provenance and auditability.

Q: How do I implement request context transformation for data standardization? A: Add transformation handlers that standardize data to common formats and structures (ISO standards, industry standards, internal standards) for interoperability.

Q: Can chains be used for request context validation in aerospace systems? A: Yes. Aerospace systems use chain of responsibility with validation handlers for safety-critical operations, with redundancy and formal verification.

Q: How do I add request context enrichment from automotive data? A: Implement enrichment handlers that fetch automotive data (vehicle telemetry, diagnostics, GPS) and add it to the request context for automotive applications.

Q: Should I use this pattern for request context validation for data security? A: Yes. Data security validation chains where each handler validates security policies (encryption, access control, audit logging) ensure data security and compliance.

Q: How do I implement request context transformation for data virtualization? A: Add transformation handlers that virtualize data access (abstracting physical storage, providing unified views) for flexible data access without moving data.

Q: Can handlers be implemented as AR/VR processing steps? A: Yes. AR/VR systems use chain of responsibility where each handler processes sensor data, performs spatial tracking, and renders virtual content.

Q: How do I add request context enrichment from energy data? A: Implement enrichment handlers that fetch energy data (consumption, generation, grid status) and add it to the request context for energy management applications.

Q: Should I use this pattern for request context validation for data sustainability? A: Yes. Data sustainability validation chains where each handler validates sustainability policies (energy efficiency, carbon footprint, resource usage) ensure environmentally responsible data processing.

Q: How do I implement request context transformation for data orchestration? A: Add transformation handlers that orchestrate data workflows (coordination, dependency management, error handling) for complex data processing pipelines.

Is this pattern suitable for small projects?

For small projects with few components, this pattern may add unnecessary complexity. Start simple and introduce the pattern when you feel the pain it solves.

How does this pattern compare to alternatives?

Each pattern makes different trade-offs. Review the variants table above and consider your specific constraints: team size, performance requirements, and future scaling plans.

Can I partially apply this pattern?

Yes. Many teams adopt patterns incrementally. Start with the core idea and add sophistication as needed. The pattern is a guide, not a strict blueprint.