DEV Community

Cover image for ๐ŸŽ‰ Goodbye asyncHandler: Native Async Support in Express 5
Mahmudur Rahman
Mahmudur Rahman

Posted on

๐ŸŽ‰ Goodbye asyncHandler: Native Async Support in Express 5

Express has long been a staple in the Node.js ecosystem, powering thousands of APIs and web applications. However, until recently, handling asynchronous route logic in Express has always felt a bit clunky โ€” particularly when it comes to error handling in async functions.

But good news: Express 5 finally brings first-class support for async/await with native promise error handling! That means you can now write clean, modern async route handlers without wrappers like asyncHandler().
In this post, weโ€™ll walk through:

  • ๐Ÿคฏ The problem in Express 4
  • โœ… The solution in Express 5
  • ๐Ÿ› ๏ธ Migration tips
  • ๐Ÿงช Real-world example

๐Ÿคฏ The Problem in Express 4
In Express 4, writing async handlers directly like this:

app.get('/users', async (req, res) => {
  const users = await getUsersFromDb(); // what if this throws?
  res.json(users);
});
Enter fullscreen mode Exit fullscreen mode

would result in an unhandled promise rejection if getUsersFromDb() throws or rejects.

Why? Because Express 4 does not understand that async functions return promises. It doesnโ€™t await them or catch their rejections automatically.
Workaround: Using asyncHandler()
To deal with this, most devs used a helper like:

const asyncHandler = fn => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

Enter fullscreen mode Exit fullscreen mode

Then youโ€™d wrap every route:

app.get('/users', asyncHandler(async (req, res) => {
  const users = await getUsersFromDb();
  res.json(users);
}));
Enter fullscreen mode Exit fullscreen mode

Clunky, right?

โœ… The Fix in Express 5
In Express 5, this boilerplate is no longer needed. You can now write:

app.get('/users', async (req, res) => {
  const users = await getUsersFromDb(); // if this throws, Express 5 will catch it
  res.json(users);
});
Enter fullscreen mode Exit fullscreen mode

๐ŸŽ‰ Express 5 automatically awaits promises and forwards errors to the error handler!

๐Ÿงช Real-World Example
Letโ€™s say you have this:

app.get('/profile', async (req, res) => {
  const user = await findUserById(req.query.id);
  if (!user) throw new Error('User not found');
  res.json(user);
});
Enter fullscreen mode Exit fullscreen mode

If anything throws (like a DB error), Express 5 will automatically send it to your error middleware:

app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).json({ message: err.message });
});

Enter fullscreen mode Exit fullscreen mode

No more asyncHandler. No more accidental unhandled rejections.
๐Ÿ› ๏ธ Migration Tips
If you're upgrading from Express 4 to 5:

  1. Remove asyncHandler() wrappers โ€” just use async route functions directly.
  2. Double-check your error middleware โ€” Express 5 continues to use the (err, req, res, next) signature.
  3. Update your dependencies โ€” install the latest Express version:
npm install express@next

Enter fullscreen mode Exit fullscreen mode

โš ๏ธ At the time of writing, Express 5 is in beta (express@5.0.0-beta.x). Keep an eye on the official changelog for production readiness.

app.use(async (req, res, next) => {
  const isValid = await validateToken(req.headers.authorization);
  if (!isValid) throw new Error('Unauthorized');
  next();
});

Enter fullscreen mode Exit fullscreen mode

Again, no try/catch needed โ€” Express 5 has your back.
๐Ÿงพ Summary
โœ… Express 5 brings native async/await support
โœ… No need for async wrappers
โœ… Clean, modern error handling
โœ… Works in both routes and middleware
โœ… Big win for developer experience!

๐Ÿ“š References

Add Basic Error Handling to an Express 5 App
๐Ÿ™Œ Conclusion
Express 5 may not seem flashy at first glance, but this feature alone dramatically simplifies writing clean, maintainable APIs with modern JavaScript. If youโ€™ve been juggling asyncHandler utilities in Express 4, it's time to celebrate and simplify.

Happy coding!
โœ๏ธ Follow me on Dev.to or GitHub for more Node.js tips, architecture guides, and backend tutorials.

Top comments (1)

Collapse
 
bilalben23 profile image
Bilal Benyoussef

Thanks! I came late, but better late than never ๐Ÿ˜„
I really hate writing try/catch in every route handler, thanks to Express for this huge, safer upgrade that removes a lot of boilerplate.