Intro
You've probably been working with Sequelize following A-Z which means you begin from migrations, models to generating the tables in the database. In this use case, you take advantage of some abstractions that Sequelize ships with such as follows:
Then, you found yourself in a use case where there's an existing database with different naming conventions for tables, fields, etc with Sequelize. Now, you need to take a Z-A approach where you would create models to adapt to the existing database schema.
This short article explains the steps you need to take in order to work with Sequelize in an existing database schema.
Step 1
npm install sequelize pg pg-hstore
touch .sequelizerc
Copy the snippet below into the
.sequelizerc
file. Note, here I want to bundle Sequelize related files into a single folder called
database
, feel free to remove the
database
from the paths if you want.
const path = require('path')
module.exports = {
config: path.resolve('./database/config', 'config.js'),
'models-path': path.resolve('./database/models'),
'seeders-path': path.resolve('./database/seeders'),
'migrations-path': path.resolve('./database/migrations'),
Now, generate the scaffolding
npx sequelize-cli init
Next up, update the database/config/config.js
with your database connection credentials.
Step 2 -- Generating models for the exiting database tables
Now let's assume that one of the tables in the existing database with the name foo_bars
has the structure below:
# tableName -> foo_bars
id INTEGER AUTOINCREMENT
first_name VARCHAR(200)
last_name VARCHAR(200)
email VARCHAR(200)
date_created DATETIME
date_updated DATETIME
If you generated the model using Sequelize command, the timestamps would be implicitly generated with names createdAt and updatedAt respectively.
Now, let's create a model that will represent the table above.
Create a file named FooBar.js
inside the database/models
folder. Copy the snippet below into the FooBar.js
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class FooBar extends Model {
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
static associate(models) {
// define association here
FooBar.init(
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
email: DataTypes.STRING,
date_created: DataTypes.DATE,
date_updated: DataTypes.DATE
// options
sequelize,
modelName: 'FooBar',
tableName: 'foo_bars',
createdAt: 'date_created',
updatedAt: 'date_updated',
underscore: true,
return FooBar;
What to note from the snippet above:
The table name was specified at it is in the existing database.
The createdAt and updatedAt specified as in the existing database
We set underscore: true because the existing schema fields are underscored. Sequelize by default uses camel case.
Other important scenarios
When the existing does not have id as the primary key
Sequelize by default assumes that every table has a primary key field with name id
. In a situation where the table does not have an id
field, we can work around it using the removeAttribute
model method as shown below:
const { Model } = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class FooBar extends Model {
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
static associate(models) {
// define association here
FooBar.init(
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
email: DataTypes.STRING,
date_created: DataTypes.DATE,
date_updated: DataTypes.DATE
// options
sequelize,
modelName: 'FooBar',
tableName: 'foo_bars',
createdAt: 'date_created',
updatedAt: 'date_updated',
underscore: true,
FooBar.removeAttribute('id');
return FooBar;
When the existing does not have createdAt and updatedAt timestamps
Just like the id
field, Sequelize by default expects that every table should have these fields which is the reason they are automatically generated alongside new migrations. The workaround for this is to set the timestamps to false in the model option as shown below:
// options
sequelize,
modelName: 'FooBar',
tableName: 'foo_bars',
createdAt: 'date_created',
underscore: true,
timestamps: false,
When one of the either createdAt or updatedAt is not needed in the existing database.
The snippet below shows the workaround by modifying the model options:
// options
sequelize,
modelName: 'FooBar',
tableName: 'foo_bars',
createdAt: 'date_created',
underscore: true,
updatedAt: false,
Conclusion