TIL: Use the `useMaster` property to fetch data from the write pool in Sequelize.

TIL: Use the `useMaster` property to fetch data from the write pool in Sequelize.

ยท

2 min read

Sequelize offers support for read replication, enabling the use of multiple servers for executing SELECT queries. In this configuration, you designate one or more servers as read replicas, while appointing one server as the primary writer. The primary writer manages all write and update operations, disseminating them to the designated replicas. It's important to note that Sequelize does not handle the actual replication process; this responsibility lies with the database backend, requiring proper setup.

const sequelize = new Sequelize('database', null, null, {
  dialect: 'mysql',
  port: 3306,
  replication: {
    read: [
      { host: '8.8.8.8', username: 'read-1-username', password: process.env.READ_DB_1_PW },
      { host: '9.9.9.9', username: 'read-2-username', password: process.env.READ_DB_2_PW }
    ],
    write: { host: '1.1.1.1', username: 'write-username', password: process.env.WRITE_DB_PW }
  },
  pool: { 
    max: 20,
    idle: 30000
  },
})

Recently, I came across a situation where I was creating(writing) data and immediately on the next line was returning the created record along with some association as an API response but the record was returning empty.

const recordIds = await fileService.create(req.files)
const files = await fileService.list({ id: recordIds })
return response(res, {record: files})

The fileService.create function creates record file records in the database and returns an array of ids of the files created. In the next line i.e. the fileService.list function takes the array of IDs, fetches the record, and returns an API response in the last line. Below is the implementation of the list function

async list(ids) {
   return await Model.findAll({
      where: {
        id: ids
      },
      ...associationQuery
    })
}

This looks plain and simple but for some reason, the list function didn't return any record. I did a lot of debugging and everything looked fine. Then I came across the property useMaster. The read replication we read about in our introduction takes some time to replicate in the read pool. The write or useMaster: true query uses a write pool to create or fetch data. So, the useMaster: true property fixes the issue of fetching data immediately after creating and it fulfills my requirement. Hence, I added useMaster: true in the above query. So the above list function becomes like this ๐Ÿ‘‡

async list(ids) {
   return await Model.findAll({
      where: {
        id: ids
      },
      ...associationQuery,
      useMaster: true // New added line
    })
}

The above code fixed the issue of data not being fetched in read replicas. I hope you like this small TIL blog. If you have any questions please comment below. Thanks for reading ๐Ÿ˜Š.

References

Did you find this article valuable?

Support AbulAsar S. by becoming a sponsor. Any amount is appreciated!