Why you should consider Koa instead of Express with Node.js

Fall 2017 update: I keep hearing good things about Micro. I have not looked deeply at it yet but it is explicit — with no middleware — so modules declare all their dependencies. Consider checking it out and let me know what you think of it compared to Koa.

There is a tendency for frameworks to create too much abstraction/convention/secret sauce/whatever for the programmer that we end up in a situation commonly known as magic. Magic is not good. It’s a black box. It means something is going on that is not well understood or is brittle. Eventually magic will bite you.

Koa has the opposite philosophy. It’s a minimalist framework sans magic, which I admire greatly about it. Few frameworks (mithril.js and j2c come to mind) have this philosophy, but the ones that do usually are gems.

Koa is Express 5.0 in spirit; it’s by the same people that created Express, and the authors changed the name to avoid upsetting people because of the backwards incompatible changes (which also happened in the Express 3 to Express 4 transition). The common code among Express and Koa has been factored out into individual modules.

“Koa and Express use the same modules. We’ve refactored Express into jshttp and pillarjs so that anyone else can make their own framework as well.” — Jonathan Ong

Koa is minimalist — around 2k LOC — and you use whatever middleware you want with it. Take a peek at the code. There are four files, none more than 600 lines long.

So Koa sounds great, but is the project going to survive? TJ has moved on to Go.

Koa has other contributors (and TJ still commits to the project). Furthermore, Koa is stable (see the commit history) meaning not much code is changing or needs to change. The project is about as finished as a software project can get; the core code is stable with most of the heavy lifting happens in middleware.

“Koa is much more stable [as in how often code is changing, not how often it is crashing]. For the past year, we’ve merged only a couple of PRs that actually changed code. There hasn’t been many new issues opened (most are for docs or about v2). We bumped it from v0 to v1 just because.” — Jonathan Ong

Koa middleware is much simpler and less hacky than Express middleware due to the way middleware flows in a stack-like manner. This allows you perform actions downstream, then filter and manipulate the response upstream. Having the middleware functions able to yield to each other makes them more composable. It may not seem important, but you may need to write or modify middleware at some point in your application’s life.

For example, in Koa you can set an X-Response-Time header like this:

function responseTime() {
return function *responseTime(next) {
var start = Date.now();
yield* next;
var delta = Math.ceil(Date.now() - start);
this.set('X-Response-Time', delta + 'ms');

Here’s what the Koa 2.0 async/await version might look like:

function responseTime() {
return async function responseTime(ctx, next) {
var start = Date.now();
await next(); // wait for other middleware to run
var delta = Math.ceil(Date.now() - start);
ctx.set('X-Response-Time', delta + 'ms');

The response time middleware records the start time, then yields to any other downstream middleware. Finally, it records the end time, calculates the difference, and sets the header. Compare to the express version: the responseTime function is called via on-headers, which is a module that monkey patches response.writeHead. The Koa version is 21 lines of code (really just 4 LOC) and doesn’t mutate response, while the express version is around 200 LOC.

One other thing worth mentioning, Koa 2 will be considered stable once async/await hits Node.js so that you don’t have to transpile. It sounds like this will arrive in Node 8.0.0 coming April 2017. (Edit: Async/await arrived in Node v7.6.0, released 2017–02–21.)

While Koa 2 is stable now (but labelled an alpha), you would have to either use harmony-async-await, babel, co or Promise.coroutine from Bluebird. If you are ok with using it you can use Koa 2.0 alpha now. (Edit: Koa 2.0.1 was released 2017–02–25.)

Take a look at https://github.com/llambda/koa-boiler for a sample project to make it easier to get started with Koa, already configured with many things you would typically want like socket.io, clustering, ETags, routing, HTTP/2, and more.

Checkout out decodotron.com for a drag-and-drop, realtime, offline base64 encoder and decoder.