Docs
Developer Documentation

Models (Sequelize)

Define database schemas, manage tables with Sequelize, and persist data to PostgreSQL.

Medusa utilizes Sequelize for database persistence with PostgreSQL. Every module defines its relational tables in src/models/ by extending the Models base class.

Tables and columns are automatically synchronized on boot without manual SQL schema migrations.

Defining a Model

A model class declares its schema definition via the schema() method:

modules/economy/src/models/Accounts.js
import { Models } from "#medusa/modules";
import { DataTypes } from "sequelize";

export class Accounts extends Models {
    constructor(medusa, module) {
        super(medusa, module, {
            name: "Accounts",
            tableName: "economy_accounts",
            timestamps: true
        });
    }

    schema() {
        return {
            id: {
                type: DataTypes.INTEGER,
                primaryKey: true,
                autoIncrement: true
            },
            guildId: {
                type: DataTypes.STRING(32),
                allowNull: false
            },
            userId: {
                type: DataTypes.STRING(32),
                allowNull: false
            },
            balance: {
                type: DataTypes.BIGINT,
                allowNull: false,
                defaultValue: 0
            },
            bank: {
                type: DataTypes.BIGINT,
                allowNull: false,
                defaultValue: 0
            },
            inventory: {
                type: DataTypes.JSON,
                allowNull: false,
                defaultValue: []
            }
        };
    }

    indexes() {
        return [
            {
                unique: true,
                fields: ["guildId", "userId"]
            }
        ];
    }
}

Model Options

When initializing a model with super(medusa, module, options):

OptionTypeDescription
namestringThe internal lookup name used when calling models.get(module, name).
tableNamestringThe physical table name in PostgreSQL. Convention: prefix with the module name (e.g. ticket_panels, moderation_cases).
timestampsbooleanWhen true, Sequelize automatically maintains createdAt and updatedAt columns.

Querying Models

Retrieve the active Sequelize model instance in any handler:

const model = this.medusa.modules.models.get("economy", "Accounts");

const account = await model.findOne({
    where: {
        guildId: guild.id,
        userId: user.id
    }
});

Common Sequelize query methods:

  • model.create({ ...values }): Inserts a new row.
  • model.findOne({ where: { ... } }): Retrieves the first matching record.
  • model.findAll({ where: { ... }, order: [...] }): Retrieves all matching rows.
  • model.findOrCreate({ where: { ... }, defaults: { ... } }): Returns existing record or creates a new one.
  • model.update({ ...fields }, { where: { ... } }): Updates records matching the filter.
  • model.destroy({ where: { ... } }): Deletes matching records.

On this page