All fair points, these are issues faced by almost everyone starting a node project. Here is a set of good practices that might help:<p>1. Use dependency injection moderately. require() calls are cached, and you can overwrite modules for testing with proxyquire/rewire. If you are using mongoose, for example, you don't need to throw around a db instance, just require('mongoose') on each module and access models with mongoose.model('User').<p>2. Separate route definitions from controllers:<p><pre><code> // tree.js
exports.getNuts = function (req, res) { ... }
// routes.js
var tree = require('./controllers/tree.js')
app.get('/nuts', tree.getNuts)
</code></pre>
3. Keep your controllers lean and move logic to your Models or a separate concerns/lib layer, so you can re-use these methods within the application.<p>4. Use a control-flow library like async, queue-async, etc. I wouldn't recommend promises as a first since they come with their own caveats. Break down logic into many small methods instead of huge chains.<p>5. Absolutely, whenever possible, break out helper methods, abstractions and common patterns in your code into separate npm modules, with it's own set of tests. This should be the final fate of everything in the /lib directory, if you have one. Doing this helps keep your codebase lean and focused, and is a good opportunity to give back to the community.<p>A rough suggestion on how to organize that last module.exports using caolan/async: <a href="https://gist.github.com/anonymous/7062240" rel="nofollow">https://gist.github.com/anonymous/7062240</a><p>Finally, it's nice to use a database driver that buffers commands before connect, so you don't need an async step on app initialization.