How can I create Express/Connect middleware which wrap each request in its own domain?
5 Answers
This set of slides on Speaker Deck gives a succinct overview:
Express middleware code from the slides:
var createDomain = require('domain').create;
app.use(function(req, res, next) {
var domain = createDomain();
domain.on('error', function(err) {
// alternative: next(err)
res.statusCode = 500;
res.end(err.message + '\n');
domain.dispose();
});
domain.enter();
next();
});

- 61,926
- 17
- 143
- 150
-
4Have You tested this? It doesn't work for me and domain.enter is undocumented on node's site. – Rafał Sobota Jul 22 '12 at 15:12
-
This does work for me. I don't know why domain.enter is undocumented though. – Kevin Dente Sep 11 '12 at 17:25
-
3I should add I'm concerned that this code calls domain.enter but there's no corresponding domain.exit. Seems like a possible leak. – Kevin Dente Sep 11 '12 at 17:45
-
This does work. `enter` Must be called. Yes, odd not in docs. – Trevor Feb 14 '13 at 22:07
-
There is a problem with this route. If you don't have an error. When is `dispose` called? I asked a question on that topic here: http://stackoverflow.com/questions/14971028/unable-to-call-dispose-on-domain-at-appropriate-time – Trevor Feb 20 '13 at 01:58
-
This does not protect against exceptions thrown in 3rd party libs... :( – Jess Oct 02 '13 at 01:36
UPDATE: The approach described below has been implemented in the connect-domain NodeJS module, which can be used in either Connect or Express applications.
As of Express 3, express.createServer
is deprecated, and its callback should be converted to a middleware. In the middleware, it's important to add the request and result objects to the request domain so that errors fired by them are handled by the domain error handler.
My middleware looks something like this:
var domain = require('domain');
app.use(function(req, res, next) {
var requestDomain = domain.create();
requestDomain.add(req);
requestDomain.add(res);
requestDomain.on('error', next);
requestDomain.run(next);
});
You can avoid adding the request and response to a request domain if you call http.createServer
from within a top-level domain, but the Domain docs seem to indicate that per-request domains are a best practice.
Note that the code above doesn't do any domain clean up actions, such as forcibly disposing the request domain. My middleware chooses instead to pass the error through the middleware stack again to be handled by specific error-handling middleware later on. YMMV.

- 3,025
- 1
- 29
- 40
-
-
@Jess, I admit that the error handling here is naive, but I'm curious what you're seeing. In theory, any exception should be captured by the domain, and provided as an "error" argument to the stack, assuming your handlers have one. – Christopher Currie Oct 02 '13 at 16:46
-
I am using sequelize which will throw an exception if the where clause does not have valid syntax for example. I cannot change the code to `emit` instead of `throw`. I've tried all the solutions listed here and none seem to catch the thrown error. – Jess Oct 02 '13 at 19:37
-
Do you have error handling middleware set up to receive the error, as described here? http://expressjs.com/guide.html#error-handling – Christopher Currie Oct 02 '13 at 20:31
-
-
1@ChristopherCurrie just thought I'd add that this approach also works in Sails- you add `connect-domain` to `sails.config.express.customMiddleware` (http-only) or use it as a policy. – mikermcneil Jan 04 '14 at 20:32
I've had good luck replacing the stock
var app = express.createServer();
with:
var domainCreate = require('domain').create;
var app = express.createServer(function (req, res, next) {
var domain = domainCreate();
domain.run(next);
});
Then in your middleware you can add properties to process.domain or add additional error handling.

- 164
- 1
- 5
-
1This may have been a good answer at one point, but `express.createServer` is deprecated. – Jess Oct 02 '13 at 01:25
-
what is the purpose of this if you don't have specific error handling for that domain? – Alexander Mills Jan 05 '16 at 09:07
This is a late answer, but check out the express-domain-moddleware module. It automatically creates a new domain for each request. The active domain can be referenced by process.domain in your routes. Here is an example:
//with domain-middleware
app.use(require('express-domain-middleware'));
app.use(app.router);
app.use(function errorHandler(err, req, res, next) {
console.log('error on request %d %s %s: %j', process.domain.id, req.method, req.url, err);
res.send(500, "Something bad happened. :(");
if(err.domain) {
//you should think about gracefully stopping & respawning your server
//since an unhandled error might put your application into an unknown state
}
});
app.get('/error', function(req, res, next) {
db.query('SELECT happiness()', process.domain.intercept(function(rows) {
fs.readFile('asldkfjasdf', process.domain.intercept(function(contents) {
process.nextTick(process.domain.intercept(function() {
throw new Error("The individual request will be passed to the express error handler, and your application will keep running.");
}));
}));
}));
});

- 1,699
- 5
- 21
- 35
-
I upvoted this because `express-domain-middleware` looks like the most well-baked (and still maintained) answer to this question. Along with `node-ok` by the same author looks like a robust solution for error handling in node/express. I'll add one more link which is also somewhat related to the same topic: how to respond to errors once they're caught: https://github.com/hapijs/boom – thom_nic Dec 03 '14 at 20:12
The domains are currently deprecated in node:
https://nodejs.org/api/domain.html
For the purpose of 'zoning errors', I've created a library which allows you to write asynchronous code in a nice way: https://github.com/vacuumlabs/yacol . One of its benefits is that you can have domains-like behavior with a very nice semantics; check it out!

- 14,388
- 4
- 30
- 35