DEV Community

Romain Lanz
Romain Lanz

Posted on • Updated on

Why you should drop ExpressJS in 2021

Express is currently, and for many years, the de-facto library in the Node.js ecosystem. When you are looking for any tutorial to learn Node, Express is presented and taught to people.

In the latest State of JS survey, Express was TOP 1 for all categories.

State of JS 2020 Results

Despite all of this, Express is not a great technology, and you should have stopped using it since 2015.

--

It is unmaintained

Express has not been updated for years, and its next version has been in alpha for 6 years.

People may think it is not updated because the API is stable and does not need change. The reality is: Express does not know how to handle async/await.

If you are using async/await code inside your route's handler or middleware, you are prone to UnhandledPromiseRejectionWarning exception. Express will not handle those exceptions for you because it does not know them.

There are multiple issues (#4360, #4348, ...) in Express' repository about people having this problem.

You should know that from Node 15, your application will crash when encountering this exception, and before this version, you will have a memory leak.

When using async/await, you should always ensure that the library accepts an AsyncFunction as a callback. Here is a great talk named Broken Promises about that.

--

It is a low-scope framework

The word "framework" is a wild term. When you are looking closer, Express is a routing library that supports middleware, but it is still called "a framework".

Evan You had a great talk about seeking the balance in a framework design. He said that we should categorize a framework by its scope.

We can categorize Express as a low-scope framework.

When you are building an application, you need more features than a routing system.

You need to:

  • access a database;
  • validate your data;
  • create an authentication layer;
  • create an authorization system;
  • etc.

All of those features are not inside Express and should be glued by yourself.

Gluing those modules yourself means taking all the risk to add memory leaks, security holes, and bugs to your application. On top of that, you are only losing time and money because you should not be the one responsible for doing that.

--

Alternatives

What are the alternatives? What should we teach to people?

Even if I believe low-scope framework should not be used, there are few people that like this style or need one for learning purposes. In this category, you should look at fastify.

This framework is well maintained, and provides an official compatibility layer for Express to help you migrate your application.

If you prefer to have a high-scope fully-featured framework that lets you focus on your business logic, you can use AdonisJS.

There is no reason to stay with Express, only future pain that you can avoid today.

--

Do I hate Express?

The goal of this section is to add a disclaimer to this article. I am not hating Express. I am sharing my perspective to help others make informed decisions and not follow the herd.

Express was one of the first frameworks in the Node.js ecosystem, and it was great for many years! But now, it is time to let it go.

I want to push the Node.js Ecosystem further and help newcomers to learn a technology that will not explode in their hands.

Discussion (77)

Collapse
eidellev profile image
Lev Eidelman Nagar

Seriously, give AdonisJS a chance. It's a real joy to work with, especially since v5.

Collapse
faraazahmad profile image
Syed Faraaz Ahmad

Coming from Rails and needing Typescript support and intellisense, Adonis v5 seems absolutely perfect!

Collapse
kasvith profile image
Kasun Vithanage

damn it looks cool

Collapse
eidellev profile image
Lev Eidelman Nagar

A little bit of shameless self-promotion:
I made a plugin for Adonis that integrates it with another great technology - inertia.js

Collapse
tairosonloa profile image
Aitor Alonso

The problem I find about Adonis is that its ORM uses an Active Record approach, what it's considered an antipattern.

Collapse
eidellev profile image
Lev Eidelman Nagar

Then by all means use a different ORM. Nothing is stopping you from integrating any 3rd party library.

Collapse
peppesilletti_4 profile image
Giuseppe Silletti

I'm not sure access to a database should have anything to do with the web framework

Collapse
jfbrennan profile image
Jordan Brennan

yerp. I'm sure some people are kind of stuck having to do that for some reason, but for the most part db + web framework is a net negative that should be avoided.

Collapse
michi profile image
Michael Z

Interested in why you think this way, could you explain further?

In my experience, it allows for seamless integration with other parts of the framework, so you don't have to write the glue code for it.
Also, frameworks come with support for multiple DB drivers that make switching the engine straight forward.

Thread Thread
peppesilletti_4 profile image
Giuseppe Silletti

It depends where the framework puts this glue code. If it's straight in the controllers for example that's not always a good idea. Maybe it can work in simple CRUD app, but for anything more complex you want your persistence logic somewhere else (far from domain business logic)

Thread Thread
jfbrennan profile image
Jordan Brennan

Yes that’s true, but my point is about monolithic server-side web frameworks vs. a more service-oriented architecture. The latter enables any client (web apps, native apps, cli) to use the same service and also avoids throwing all traffic at the same server.

Collapse
robinvanderknaap profile image
Robin van der Knaap

I'm sure access to a database should never have anything to with the web framework. :)

Collapse
pradeep_io profile image
Pradeep Sharma • Edited on

Strongly disagree. Despite the good intention of the author, this article may lead people to make bad decisions. Here's why

  • While js has evolved in terms of syntax and new concepts, fundamentals are still the same. If you want to build a reliable system that lasts longer, stick to the fundamentals(simple function over async/await), stick to the code that has been vetted by many people in the past. The js community is really excited about the modern js(so am I) but jumping on it without looking at the support for the essential tools is a mistake.
  • Being a low-scope framework is a feature, not bug. I stick to express 4 because I want reliability and easy maintenance. And I'm not sacrificing anything in doing so(except my urge to jump on trying new shiny things that might look making my life easier in short term).
  • Making a good system that doesn't need breaking upgrades for many years is really hard and I believe express has done that. The question to ask - Is there any important issue in express 4 that has been pending for last one year? Have a look at the express recent closed issues
Collapse
larsonnn profile image
Lars Feldeisen

Also nodejs 14 LTS is from jan 2020 and express 5 is from from march 2020. Express is always pretty stable.

UnhandledPromiseRejectionWarning <- thats bad programing style. :) Why should express handle it in first place.

Collapse
dominuskelvin profile image
Kelvin Omereshone

I have to agree with you on these points.

Collapse
sebastienlorber profile image
Sebastien Lorber

I do agree that the async/await should be fixed, but...

React is somehow also a low-scope framewor, does it mean it's bad compared to Angular?
What do you think about tools using the unix philosophy? Doing one thing well?

In my opinion, when you are an experienced developer in a given ecosystem, you prefer to assemble low-scope tools yourself instead of relying on opinionated choices of a high scope framework.

Collapse
erellsworth profile image
Edward Ellsworth

Last production release of Express was about 2 years ago, not 6.
github.com/expressjs/express/relea...

Just because they haven't released a major version in a while doesn't mean it's unmaintained. There's still plenty of active development going on.

Collapse
zackdotcomputer profile image
Zack Sheppard

Whenever a getting started says to use Express, my default has been to use Koa, which works ok and had mostly been my default since it was billed as "the Express founders decided to make express but with better async and fewer leaks." This thread is full of great alternatives, though - looking forward to checking them out.

Collapse
miguellattuada profile image
Miguel Lattuada

I was thinking the same, also Hapi is missing here, it has been around for some time like express and koa.

Collapse
jdrydn profile image
James

I personally love the single argument ctx style of thinking - especially since the request-level context is often passed to other functions!

Collapse
yoursunny profile image
Junxiao Shi • Edited on

I tend to select different frameworks every time I start a new project, so that I can reduce the risk when a framework starts to break down.

It's my first time knowing the technical shortcoming of Express.
I have one Express app full of await s. Looks like I'll have to redo that app.

Collapse
codr profile image
Ilya Nevolin

I feel offended by the title. ExpressJS is still perfectly valid to use, it's very stable and given its ecosystem there exist many plugins for authentication/security/etc. But I understand what you want.

Collapse
benruns profile image
Ben Patterson • Edited on

I wouldn't say the issue is async/await exactly or that it's new. It's never really handled Promises well.

Most common "solution" is to create a little asyncify function.

(quick off the top of my head, didn't debug this)

function asyncify(fn) {
 return (req, res, next)=>Promise.resolve(fn(req,res,next)).catch(next);
}
Enter fullscreen mode Exit fullscreen mode

and then use it around functions in your express app

app.get('/', asyncify(async function(req, res, next){  return "hello world" }))
Enter fullscreen mode Exit fullscreen mode

It's mildly annoying but the automatic handling of async functions isn't a deal breaker for me. You'd also be surprised how often you don't need an auth layer or a database built in for small projects.

There is quite a bit missing express, but that's what I like about it. It's flexible and easy to hack on top of. It's not the right tool for every project and probably not the best choice if you want something with batteries included. Like any project, you check your requirements and then choose what tools you use. I'll probably keep using express for a while just because of how flexible it is.

Also, the source code is a nice read if you every need to really dive into debugging.

(Unpopular opinion, I'll just use rails or django if I want something stable, with a database, with built testing and batteries included)

Collapse
jankapunkt profile image
Jan Küster

Is express becoming the jQuery of the backend?

Collapse
karlkras profile image
Karl Krasnowsky

Jquery is hardly a "low scope" framework.

Collapse
jfbrennan profile image
Jordan Brennan

Haven’t heard “low-scope” yet, so thanks for that. I prefer low-scope frameworks. I like the ease-of-use, low barrier to entry, flexibility, freedom to use complimentary libraries. And the relatively low commitment that makes abandoning them possible really wins me over. I’ll be taking a look at fastify

Collapse
patarapolw profile image
Pacharapol Withayasakpunt

Loved it, mainly because of validation with ajv and fast json stringify.

And, simple yet perfect validation is a deal breaker for me.

Also, integrates well with OpenAPI.

Collapse
chadalen profile image
Chad Alen

aex looks like nest.js have you ever used that?

Collapse
tam2 profile image
Tam

Recently started using nestjs for a new project, really good to use and adds structure to code, however it does still use express or fastify

Collapse
weakish profile image
Jang Rush

It is said the next generation of express (express 5) will play nicely with async/await (I've waited for the next generation for years, though). BTW, I'd like to translate this post to Chinese, and publish the translation at nextfe.com. Can you give me the permission to do so? Thanks in advance.

Collapse
romainlanz profile image
Romain Lanz Author

If you point to the official article, I see no reason not to translate it to whatever language you want.

Collapse
weakish profile image
Jang Rush

Finished the translation last weekend: nextfe.com/drop-expressjs/ There is a backlink to this original post at the beginning of the translated text.

Collapse
kostyatretyak profile image
Костя Третяк • Edited on

If you like working with TypeScript, with Dependency Injection, with good modularity, and you don't mind trying the beta version of the new framework, you can try Ditsmod.

Yes, it's like Nest.js, but it is simpler, has built-in support for nested routes, has a clearer scopes of providers (per application, per module, per request), and has no Express under the hood.

If you are cloning repository, then you can run the examples as follows:

yarn start1
# OR
yarn start2
# OR
yarn start3
# and so on
Enter fullscreen mode Exit fullscreen mode
Collapse
malitov profile image
Pavlo Malitov

Hi from Dou)) ✌️

Collapse
jdrydn profile image
James • Edited on

If you are using async/await code inside your route's handler or middleware, you are prone to UnhandledPromiseRejectionWarning exception.

Is this true if you try-catch your Async expressions?

app.use(async (req, res, next) => {
  try {
    const post = await posts.create(req.body);
    res.status(200).json(post);
  } catch (err) {
    next(err);
  }
});
Enter fullscreen mode Exit fullscreen mode
Collapse
lukaszahradnik profile image
Lukáš Zahradník

Express is aiming to be minimal and there are frameworks with more features built on top of it. If it wasn't minimal and would contain ORM etc. it would be for the worse as the said frameworks would have to deal with it.

This way you don't have one monolith framework, but something that you can configure how you want/need.

Collapse
parkerproject profile image
Parker

I like the services approach moleculer.services, never looked back since jumping on that.

Collapse
prashanthr profile image
Prashanth Rajaram (He/Him) • Edited on

I agree with the thoughts in your post and especially your disclaimer. Everything has tradeoffs. I think Express is a good starting point for new comers to understand what they can do with a basic framework. One can then take it from there.

I like Fastify's benchmarks section where it compares features and speed:
github.com/fastify/fastify#benchmarks

Collapse
gilbertoalbino profile image
Gilberto Albino • Edited on

If you were to inquire who knows how to respond to a simple POST request in Node.JS you are very likely to realize that nobody knows Node.JS. The majority of people only know how to use Frameworks and Libraries... and arrogantly label themselves "Node.JS developers".
I sincerely think that Express will be the very last issue of a company loosing any cent of money to worry about when choosing a Node.JS framework. I would worry about developers that don't know how and what Node.JS is supposed to be.

Collapse
leandroandrade profile image
Leandro Andrade

Thanks for share your point of view. About use async/await on express, I using express-async-errors on top of bootstrap app. Something like this: github.com/leandroandrade/node-ess...

This library allow to handle async errors.

Until now I'm not catch a bug report on my apps.

Collapse
avidcoder123 profile image
avidcoder123

Amazing article, I never liked Express due to its low scope philosophy but I didn't know how dangerous async/await was in Express!

Collapse
patarapolw profile image
Pacharapol Withayasakpunt

It always is, until you are aware.

Collapse
dominuskelvin profile image
Kelvin Omereshone

Awesome article. piecing things together have been one of the pains for me in Express. Before I found Sails it gave me the creeps.

I will encourage Node.js developers to also try out a fully featured high scope framework like Sails.

I wrote a getting started piece on LogRocket

blog.logrocket.com/building-a-node...

Collapse
alexigbokwe profile image
Alex Igbokwe

You can also check out Expresswebjs. Expresswebjs.com

Collapse
corysus profile image
Almir

AdonisJS is nice and only bad thing is documentation, for v4 there is OK documentation but for v5 unfortunately not :( Also for v5 upgrade from version to version is not good. You say express not move from alpha6 many years, we are wait for first v5 release about two years. I really love Adonis but you must work on community and documentation. Good luck!

Collapse
pawelmiczka profile image
Paweł Miczka

If you like TypeScript (as I do) try nestjs.com . I like the concept of structuring folders in right way and an idea to separate code into modules. Really elegant way to write good code.

Collapse
kostyatretyak profile image
Костя Третяк

Although Nest.js is better structured than Express.js, the lack of built-in prefix support for nested routes is frustrating. Yes, I know that there are third-party modules that implement this feature, but it's still strange that the author of Nest.js didn't do it out of the box.

Collapse
pawelmiczka profile image
Paweł Miczka

Structuring like

user (directory)
-- group (directory inside user directory)

Doesn't work? Shouldn't that create nested routes? Like /user/group

Thread Thread
kostyatretyak profile image
Костя Третяк

I'm talking about nested routes, like /api/posts/123/comments/456

Collapse
larsonnn profile image
Lars Feldeisen

You can just write a tiny web framework (routing, "middleware") by yourself in few hours. Done this called: bunserver and no dependencies.

with a little work to do it's stable, tested and ready for production. That's how easy it is in JS to replace some Frameworks. Ofc express etc do alot more. But when writing microservices or you just want routing with a little middleware magic... its perfect.

Collapse
mdrobny profile image
Michał Drobniak

I support this opinion, thanks for the article. I don't consider Express as stable and mature anymore. For me it's a legacy, it doesn't evolve and it's time to stop using it. I recommend Hapi :) serves me well for years

Collapse
mjgs profile image
Mark Smith • Edited on

I think it depends on the size or project you are building and your experience level.

When I first started writing NodeJS web servers I started with a framework for all the reasons the author describes. But I found that the framework was always getting in the way. There was so much code, I found it very difficult to figure out how to integrate various standard middleware, I was learning the framework concepts rather than the more basic concepts.

That particular framework was built on top of express anyway, do one day when I’d had enough if hitting my head against a metaphorical brick wall, I re-wrote the app using just express.

It was one of the most liberating things I ever did on my programming journey.

Suddenly I was able to learn how to build web apps unhindered by the framework.

Of course you have to build things yourself, but there are modules available for most things. I have become a better programmer because of it. Upgrades are easier, replacing a specific part of an app is easier.

Having said that, I can see how if you are building a very big app, having a framework could be very beneficial. I would be happy to use one now, because I have the skills and experience to be able to work with a framework.

An analogy that might be appropriate: a big framework is like an entire building site for constructing a huge sky scrapper. That’s a lot of complexity, but you might need it to build a sky scrapper quickly and on budget. ExpressJS is useful for situations where you are building a shed or a small house, but you might also find a use for it building a sky scrapper, but you’ll have to assemble a lot of things yourself, so might not be appropriate in all situations.

Collapse
alexigbokwe profile image
Alex Igbokwe

For me express is a good framework. It has and is still serving it's purpose. If you want to have a high scope featured framework still with express, then you have Expresswebjs. You can check it out at expresswebjs.com/

Collapse
barelyhuman profile image
Reaper

github.com/barelyhuman/seed-fullstack
I'm just using next.js for everything at this point.
If i do want to separate backend from frontend then I have github.com/barelyhuman/ftrouter which I rarely use anymore but then it's not maintained any more because I was the sole user

Collapse
larsolt profile image
Lars

Thanks, never heard of this