3.3. Module Link

In this chapter, you’ll learn what a module link is and how to define one.

Medusa's modular architecture isolates modules from one another to ensure they can be integrated into your application without side effects. Module isolation has other benefits, which you can learn about in the Module Isolation chapter. Since modules are isolated, you can't access another module's data models to add a relation to it or extend it. Instead, you use a module link.

A module link forms an association between two data models of different modules while maintaining module isolation. Using module links, you can build virtual relations between your custom data models and data models in the commerce modules, which is useful as you extend the features provided by the commerce modules. Then, Medusa creates a link table in the database to store the IDs of the linked records. You'll learn more about link tables later in this chapter.

For example, the Brand Customizations Tutorial shows how to create a Brand Module that adds the concept of brands to your application, then link those brands to a product.


Module links are defined in a TypeScript or JavaScript file under the src/links directory. The file defines the link using defineLink from the Modules SDK and exports it.

For example:

src/links/blog-product.ts
1import BlogModule from "../modules/blog"2import ProductModule from "@medusajs/medusa/product"3import { defineLink } from "@medusajs/framework/utils"4
5export default defineLink(6  ProductModule.linkable.product,7  BlogModule.linkable.post8)

The defineLink function accepts as parameters the link configurations of each module's data model. A module has a special linkable property that holds these configurations for its data models.

In this example, you define a module link between the blog module's post data model and the Product Module's Product data model.

After defining the link, run the db:sync-links command:

Terminal
npx medusa db:sync-links

The Medusa application creates a new table for your module link to store the IDs of linked records.

You can also use the db:migrate command, which runs both the migrations and syncs the links.

Use either of these commands whenever you make changes to your link definitions. For example, run this command if you remove your link definition file.


When you define a module link, the Medusa application creates a table in the database for that module link. The table's name is a combination of the names of the two data models linked in the format module1_table1_module2_table2, where:

  • module1 and module2 are the names of the modules.
  • table1 and table2 are the table names of the data models.

For example, if you define a link between the Product data model from the Product Module and a Post data model from a Blog Module, the table name would be product_product_blog_post.

The table has two columns, each storing the ID of a record from the linked data models. For example, the product_product_blog_post table would have columns product_id and post_id. These columns store only the IDs of the linked records and do not hold a foreign key constraint.

Then, when you create links between records of the data models, the IDs of these data models are stored as a new record in the link's table.

TipYou can also add custom columns in the link table as explained in the Add Columns to Link Table chapter.

Diagram illustration for module links


Use module links when
  • You want to create a relation between data models from different modules.
  • You want to extend the data model of another module.
Don't use module links ifYou want to create a relationship between data models in the same module. Use data model relationships instead.

By default, a module link establishes a one-to-one relation: a record of a data model is linked to one record of the other data model.

To specify that a data model can have multiple of its records linked to the other data model's record, use the isList option.

For example:

Code
1import BlogModule from "../modules/blog"2import ProductModule from "@medusajs/medusa/product"3import { defineLink } from "@medusajs/framework/utils"4
5export default defineLink(6  ProductModule.linkable.product,7  {8    linkable: BlogModule.linkable.post,9    isList: true,10  }11)

In this case, you pass an object of configuration as a parameter instead. The object accepts the following properties:

  • linkable: The data model's link configuration.
  • isList: Whether multiple records can be linked to one record of the other data model.

In this example, a record of product can be linked to more than one record of post.

Your module link can also establish a many-to-many relation between the linked data models. To do this, enable isList on both sides of the link.

For example:

Code
1import BlogModule from "../modules/blog"2import ProductModule from "@medusajs/medusa/product"3import { defineLink } from "@medusajs/framework/utils"4
5export default defineLink(6  {7    linkable: ProductModule.linkable.product,8    isList: true,9  },10  {11    linkable: BlogModule.linkable.post,12    isList: true,13  }14)

To enable delete cascade on a link so that when a record is deleted, its linked records are also deleted, pass the deleteCascade property in the object passed to defineLink.

For example:

Code
1import BlogModule from "../modules/blog"2import ProductModule from "@medusajs/medusa/product"3import { defineLink } from "@medusajs/framework/utils"4
5export default defineLink(6  ProductModule.linkable.product,7  {8    linkable: BlogModule.linkable.post,9    deleteCascade: true,10  }11)

In this example, when a product is deleted, its linked post record is also deleted.


As mentioned in the Module Link's Database Table section, the name of a link's table consists of the names of the modules and the data models' table names.

So, if you rename a module or a data model's table, then run the db:sync-links or db:migrate commands, you'll be asked to delete the old link table and create a new one.

TipA data model's table name is passed in the first parameter of model.define, and a module's name is passed in the first parameter of Module in the module's index.ts file.

For example, if you have the link table product_product_blog_post and you rename the Blog Module from blog to article, Medusa considers the old link definition deleted. Then, when you run the db:sync-links or db:migrate command, Medusa will ask if you want to delete the old link table, and will create a new one with the new name product_product_article_post.

To resolve this, you can rename the link table in the link definition.

If you need to rename a module or its data model's table, you can persist the old name by passing a third parameter to defineLink. This parameter is an object of additional configurations. It accepts a database property that allows you to configure the link's table name.

For example, after renaming the Blog Module to article, you can persist the old name blog in the link table name:

Code
1import ArticleModule from "../modules/article"2import ProductModule from "@medusajs/medusa/product"3import { defineLink } from "@medusajs/framework/utils"4
5export default defineLink(6  ProductModule.linkable.product,7  {8    linkable: ArticleModule.linkable.post,9    isList: true,10  },11  {12    database: {13      table: "product_product_blog_post",14    },15  }16)

In this example, you set the table property in the database object to the old link table name product_product_blog_post, ensuring that the old link table is not deleted.

This is enough to rename the link table when you rename a module. If you renamed a data model's table, you need to also run the db:sync-links or db:migrate commands, which will update the column names in the link table automatically:

Terminal
npx medusa db:migrate

To delete a module link definition, remove the link file from the src/links directory. Then, run the db:sync-links or db:migrate command to delete the link table from the database:

Terminal
npx medusa db:migrate
Was this chapter helpful?
Ask Anything
FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break