Pipeline / Middleware Pattern: Assembly Line in a Factory
The Pipeline or Middleware Pattern is a way to handle a sequence of operations in a flexible and reusable manner. It's especially useful when dealing with requests that need to pass through multiple processing stages—each performing a specific task such as logging, authentication, validation, or transformation.
Instead of one large method doing everything, the pattern allows you to build a pipeline of smaller, single-responsibility components. Each part decides whether to pass the flow along or stop it. This is commonly seen in ASP.NET middleware but can be applied anywhere.
Real-Life Analogy: Assembly Line in a Factory
Imagine a factory where products are built on an assembly line. A raw item enters at the start and goes through several stations. Each station adds something: one installs the wheels, another paints it, and yet another checks quality. Every station knows what to do, and the product flows down the line until it's finished—or rejected if something is wrong.
- Item on the Line → The request or data flowing through the pipeline
- Each Station → A middleware or handler that performs a task
- Assembly Sequence → The order of middleware matters
- Quality Check Can Stop Flow → Middleware can halt the process
- Easy to Add/Remove a Station → Middleware components are modular

Benefits of Pipeline / Middleware Pattern
- Separation of concerns: Each component does only one thing
- Reusable steps: Middleware can be reused across applications
- Configurable flow: Order of steps can be easily changed
- Conditional logic: Middleware can stop the pipeline if needed
What to Implement
Key elements to build this pattern:
- Request or Context object: Carries information down the line
- Middleware interface: Each step should implement a common method like
Invoke()
- Next delegate: A function to call the next middleware
- Pipeline builder: Combines middleware in order
How It Works in C#
public interface IMiddleware
{
Task InvokeAsync(HttpContext context, Func<Task> next);
}
public class LoggingMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, Func<Task> next)
{
Console.WriteLine("Before request");
await next();
Console.WriteLine("After request");
}
}
public class AuthMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, Func<Task> next)
{
if (!context.User.Identity.IsAuthenticated)
{
context.Response.StatusCode = 401;
return;
}
await next();
}
}
// Pipeline runner
public class Pipeline
{
private readonly List<IMiddleware> _middlewares = new();
public void Add(IMiddleware middleware)
{
_middlewares.Add(middleware);
}
public Task ExecuteAsync(HttpContext context)
{
Task next() => Task.CompletedTask;
foreach (var middleware in _middlewares.AsEnumerable().Reverse())
{
var current = middleware;
var nextCopy = next;
next = () => current.InvokeAsync(context, nextCopy);
}
return next();
}
}
When Should You Use It?
- When you have a series of steps that must be applied in order
- When you want to make request processing more modular and maintainable
- When each step might conditionally stop the process or modify input/output
When Not to Use It: Avoid this pattern when your process is linear and simple, with no real need for extension or reuse of steps.
Where Is It Used in the Real World?
The Pipeline / Middleware Pattern is everywhere in modern backend systems. In fact, you’re likely using it even if you didn’t build it yourself.
- ASP.NET Core: Middleware handles HTTP requests (e.g., routing, auth, logging)
- Express.js (Node): Uses the same concept with middleware functions
- Data processing flows: ETL pipelines and message brokers often follow this pattern
- Validation layers: Input validation can be broken into separate steps
Final Thoughts
The Pipeline or Middleware Pattern brings structure, clarity, and flexibility to your applications. Whether you're handling web requests or processing data, breaking logic into isolated steps helps keep systems clean and easy to maintain. It also makes it easier to inject new behaviour without breaking everything else.