When I first started building APIs with Express.js, every async controller looked the same. I would write a try block, perform some database operations, and then write a catch block that called next(error).

It worked, so I copied the same pattern into every controller. One controller became ten. Ten became fifty. Eventually, I realized that half of my controller code wasn't actually business logic, it was just repetitive error handling.

That's when I discovered the Async Handler pattern.

The Problem

A typical Express controller often looks like this: