ASP.NET Core Middleware: Patterns, Pitfalls, and Performance
Middleware sits at the heart of every ASP.NET Core application, governing how requests flow through your system. When implemented well, it enables powerful capabilities like authentication, logging, and caching. When implemented poorly, it can introduce subtle bugs, performance bottlenecks, and even security vulnerabilities.
This comprehensive guide will walk you through:
Core middleware concepts and the request pipeline
Practical examples you can use in production today
Critical anti-patterns and how to avoid them
Performance considerations for high-traffic applications
Advanced patterns for complex scenarios
Understanding the Middleware Pipeline
ASP.NET Core processes HTTP requests through a pipeline of middleware components. Each component can:
Process incoming requests
Modify the request or response
Short-circuit the pipeline (like returning a 404)
Call the next middleware in sequence
Basic Middleware Structure
Registration Methods
Middleware Examples
1. Timing Middleware (Measure Request Duration)
Key Features:
Accurate timing with
Stopwatch
Proper error handling in
finally
blockStructured logging
2. Feature Flags Middleware
Best Practices:
Async feature checks
Early return for disabled features
Clean separation of concerns
Critical Anti-Patterns and Fixes
1. The Deadlock Trap
❌ Dangerous Code:
✅ Safe Alternative:
Why This Matters:
ASP.NET Core's thread pool is limited. Blocking threads can quickly lead to thread starvation.
2. The Captured Dependency Problem
❌ Problematic Code:
✅ Correct Approach:
Key Insight:
Middleware is singleton by default. Scoped services must be resolved in InvokeAsync
.
Performance Optimization Techniques
1. Minimize Allocations
2. Use Pooled Objects
3. Async All the Way
Advanced Patterns
1. Branching Middleware
2. Terminal Middleware
3. Middleware Factories
Conclusion: Building Robust Middleware
Always use async - Avoid
.Result
and.Wait()
Respect service lifetimes - Never capture scoped services
Mind your order - Middleware sequence matters
Optimize performance - Reduce allocations, use pooling
Handle errors gracefully - Don't swallow exceptions
By following these principles and avoiding common pitfalls, you'll create middleware that's:
✅ Reliable
✅ Performant
✅ Maintainable
✅ Secure