
Published: January 2026 Reading time: 35 minutes Keywords: #design-patterns #decorator #middleware #composition #typescript #expressjs #nestjs
Your lead walks in. "We need rate limiting on all authenticated endpoints." You look at your codebase: 47 controllers, each with duplicated auth, logging, and validation logic.
The naive approach: Add rate limiting to all 47 controllers manually.
The reality: Express.js, NestJS, and AWS Lambda handle this with zero duplication. They use the Decorator Pattern to compose behaviors dynamically.
This article shows you how to build APIs where adding a feature like rate limiting takes 1 minute, not 3 days.
async function createPost(req: Request, res: Response) {
// Auth check (copy #1 of 47)
const token = req.headers.authorization;
if (!token) return res.status(401).send();
// Logging (copy #2 of 47)
logger.info('Creating post');
// Business logic (only 5 lines!)
const post = await db.posts.create(req.body);
res.json(post);
}
Problems:
We wrap the core handler in "Decorators" (Middleware) that add functionality without changing the handler.
const createPost = compose(
errorHandler,
logging,
authenticate,
rateLimit(10, 60000), // 10 req/min
validateBody(postSchema)
)(createPostHandler);
(Rest of the expanded content previously generated by sub-agent...)
Free and paid products to turn ideas into a foundation you can actually ship.
13 products availableContinue exploring similar topics

The Flyweight Pattern is how Figma, Google Maps, and VS Code render millions of objects with minimal memory.

The Composite Pattern is how GitHub, Linear, and Slack manage hierarchical permissions with zero code duplication.

Stop letting legacy code pollute your modern architecture. Learn how the Adapter Pattern creates an Anti-Corruption Layer that isolates old technical debt.
A 47-point checklist to find bugs, security risks, and performance issues before launch.
Production-tested templates trusted by developers. Save weeks of setup on your next project.