Search code examples
javascriptnode.jsfunctional-programmingdomain-driven-designinversion-of-control

DDD: using db layer as a singleton, could this be problematic


I recently downloaded a ddd boilerplate to get an example of a javascript functional approach to ddd. As I went through and analyzed the code I reached the awilix ioc setup and am a little confused on this approach. The code below is directly from the container.js file (https://github.com/joshuaalpuerto/node-ddd-boilerplate):

const { createContainer, asValue, asFunction } = require('awilix')
// you can do this
const app = require('./app')
const server = require('./interfaces/http/server')
const router = require('./interfaces/http/router')
const auth = require('./interfaces/http/auth')
const config = require('../config')
const logger = require('./infra/logging/logger')
const database = require('./infra/database')
const jwt = require('./infra/jwt')
const response = require('./infra/support/response')
const date = require('./infra/support/date')
const repository = require('./infra/repositories')

const container = createContainer()

// SYSTEM
container
  .register({
    app: asFunction(app).singleton(),
    server: asFunction(server).singleton(),
    router: asFunction(router).singleton(),
    logger: asFunction(logger).singleton(),
    database: asFunction(database).singleton(),
    auth: asFunction(auth).singleton(),
    jwt: asFunction(jwt).singleton(),
    response: asFunction(response).singleton(),
    date: asFunction(date).singleton(),
    config: asValue(config),
    repository: asFunction(repository).singleton()
  })

module.exports = container

If endpoints are being accessed that access the db layer via a repository layer, should the database layer be a singleton? I would think this could open the door to unwanted side effects if all users are accessing the same db connection. Granted, I am probably missing something as this is my first time seeing awilix being used but it sure looks like only one instance of the database layer is being utilized. Am I missing something here and is this actually safe or could this really lead to issues?


Solution

  • Remember that NodeJS is single-threaded. There is only one node process running, so having a singleton is not bad. This is what saves machine resources over other architectures (like Java) where each request is it's own thread and memory etc. The single instance is just the means of accessing the DB.

    Also remember that NodeJS is good at lots of I/O happening at once. It takes quite a bit to slow the whole thing down. Even though it is a DB singleton, that may not be an issue for your application. There may never be a bottleneck at the DB level. Or there may not be a (noticeable) delay with simultaneous request. Rather than each request build a DB connection (which could be costly in time and resources), the DB connection is shared. Ease of getting started early in a project is more valuable than figuring out highly-scalable things (which could have different solutions when the time comes.)

    One last thing. The singleton is an instance of sequelize. Sequelize is a really popular NodeJS DB connection, and can even be configured with a connection pool. Now your single DB instance is managing requests via multiple connections which will take you to the next level scalability.