Sequelize ORM
Sequelize is a mature, promise-based ORM for SQL databases (Postgres, MySQL, MariaDB, SQLite, MSSQL). Like Mongoose for MongoDB, it lets you define models and work with objects instead of writing SQL — handling associations, validation, and migrations. It's the most established Node SQL ORM, with a large feature set and a correspondingly large API. This page covers models, associations, querying, and where Sequelize fits relative to Prisma and TypeORM.
Setup and connection
npm install sequelize pg # + the driver for your DB (pg, mysql2, ...)
import { Sequelize, DataTypes } from 'sequelize'
export const sequelize = new Sequelize(process.env.DATABASE_URL, {
dialect: 'postgres',
pool: { max: 10, idle: 30_000 }, // Sequelize manages the pool
logging: process.env.NODE_ENV !== 'production' ? console.log : false,
})
await sequelize.authenticate() // verify the connection at startupDefining a model
const User = sequelize.define('User', {
name: { type: DataTypes.STRING, allowNull: false },
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: { isEmail: true }, // model-level validation
},
age: { type: DataTypes.INTEGER, validate: { min: 0, max: 150 } },
role: { type: DataTypes.ENUM('user', 'admin'), defaultValue: 'user' },
}, {
tableName: 'users',
timestamps: true, // adds createdAt / updatedAt
})CRUD
// Create:
const user = await User.create({ name: 'Ada', email: 'ada@x.com' })
// Read:
const all = await User.findAll({ where: { role: 'user' }, limit: 20, order: [['createdAt', 'DESC']] })
const byPk = await User.findByPk(req.params.id)
const one = await User.findOne({ where: { email: 'ada@x.com' } })
// Update (on an instance, or in bulk):
user.name = 'Ada L.'
await user.save()
await User.update({ role: 'admin' }, { where: { id: 1 } })
// Delete:
await user.destroy()
await User.destroy({ where: { active: false } })Querying with operators
import { Op } from 'sequelize'
await Product.findAll({
where: {
price: { [Op.between]: [10, 100] },
category: { [Op.in]: ['book', 'toy'] },
name: { [Op.iLike]: '%pro%' }, // case-insensitive (Postgres)
[Op.or]: [{ featured: true }, { rating: { [Op.gte]: 4.5 } }],
},
attributes: ['id', 'name', 'price'], // projection (like SQL SELECT cols)
})Associations — the relational core
// Declare relationships; Sequelize manages foreign keys + join helpers:
User.hasMany(Post, { foreignKey: 'authorId', as: 'posts' })
Post.belongsTo(User, { foreignKey: 'authorId', as: 'author' })
Post.belongsToMany(Tag, { through: 'PostTags' }) // many-to-many via join table
Tag.belongsToMany(Post, { through: 'PostTags' })
// Eager-load associations in one query (a real SQL JOIN):
const posts = await Post.findAll({
include: [{ model: User, as: 'author', attributes: ['name'] }],
})
posts[0].author.nameTransactions
// Managed transaction — auto commit/rollback around the callback:
await sequelize.transaction(async (t) => {
await Account.decrement('balance', { by: 100, where: { id: 1 }, transaction: t })
await Account.increment('balance', { by: 100, where: { id: 2 }, transaction: t })
// throw anywhere → automatic ROLLBACK; otherwise auto COMMIT
})Migrations, not `sync`
// Convenient in dev only — NEVER in production:
await sequelize.sync({ alter: true }) // tries to reshape tables to match models
// Production: use sequelize-cli migrations (versioned, reviewable, reversible).Sequelize vs the alternatives
Sequelize | Prisma | TypeORM | |
|---|---|---|---|
Maturity | Very mature, huge ecosystem | Newer, fast-growing | Mature |
TypeScript | Add-on typings, imperfect | Excellent (generated client) | Decorator-based, native TS |
Schema source | JS model definitions | A | Entity classes |
Style | Active Record + query API | Generated, type-safe client | Active Record / Data Mapper |