Simple explanation for Chain of Responsibility Pattern

Situation: You’re Building an HTTP Request Handler

You write a class HttpRequestHandler to process incoming API requests.

Initially, it just needs to:

  1. Authenticate the user
  2. Validate the request body
  3. Process the request

All good.

Then Requirements Changed

Suddenly you need to:

  • Add rate limiting
  • Add logging
  • Add feature flag check
  • Add IP whitelisting
  • And maybe do all this only in certain environments

Now you’re like:

“Should I just throw everything inside HttpRequestHandler? Maybe with 10 if-else blocks?”

But deep down, you know it’s a trap.

What’s the Problem?

  • You’re turning one class into a god object.
  • Every new rule = more clutter.
  • You can’t re-use or reorder logic easily.
  • Testing individual behaviors becomes painful.
  • Changing one thing might break another.

How Chain of Responsibility Saves You

Instead of one big handler, you create a chain of small handlers, each doing one job:

  1. AuthHandler → checks authentication
  2. RateLimitHandler → checks quota
  3. ValidationHandler → validates input
  4. BusinessLogicHandler → executes actual logic

Each handler:

  • Implements a common interface (e.g., handleRequest).
  • Decides to process the request, stop the chain (e.g., reject invalid input), or pass it to the next handler.
  • If no next handler exists, the chain ends with a default action (e.g., return a response).

You can now add, remove, or reorder handlers without touching others. Super clean. Super flexible.

When Should You Use It?

  • When a request needs to pass through multiple processing steps.
  • When steps might be optional, conditional, or environment-dependent.
  • When you want to decouple concerns - each class focuses on just one job.

Real World Dev Examples

  • Middleware in Express.js or Spring Security Filters? Pure CoR.
  • Event pipelines, logging systems, email processors? All use it.
  • Support tickets getting escalated? That’s CoR in real life.