3.2.3. Module Isolation

In this chapter, you'll learn how modules are isolated, and what that means for your custom development.

Summary
  • Modules can't access resources, such as services or data models, from other modules.
  • Use Medusa's linking concepts, as explained in the Module Links chapters, to extend a module's data models and retrieve data across modules.

How are Modules Isolated?#

A module is unaware of any resources other than its own, such as services or data models. This means it can't access these resources if they're implemented in another module.

For example, your custom module can't resolve the Product Module's main service or have direct relationships from its data model to the Product Module's data models.


Why are Modules Isolated#

Some of the module isolation's benefits include:

  • Integrate your module into any Medusa application without side-effects to your setup.
  • Replace existing modules with your custom implementation, if your use case is drastically different.
  • Use modules in other environments, such as Edge functions and Next.js apps.

How to Extend Data Model of Another Module?#

To extend the data model of another module, such as the product data model of the Product Module, use Medusa's linking concepts as explained in the Module Links chapters.


How to Use Services of Other Modules?#

If you're building a feature that uses functionalities from different modules, use a workflow whose steps resolve the modules' services to perform these functionalities.

Workflows ensure data consistency through their roll-back mechanism and tracking of each execution's status, steps, input, and output.

Example#

For example, consider you have two modules:

  1. A module that stores and manages brands in your application.
  2. A module that integrates a third-party Content Management System (CMS).

To sync brands from your application to the third-party system, create the following steps:

Example Steps
1const retrieveBrandsStep = createStep(2  "retrieve-brands",3  async (_, { container }) => {4    const brandModuleService = container.resolve(5      "brandModuleService"6    )7
8    const brands = await brandModuleService.listBrands()9
10    return new StepResponse(brands)11  }12)13
14const createBrandsInCmsStep = createStep(15  "create-brands-in-cms",16  async ({ brands }, { container }) => {17    const cmsModuleService = container.resolve(18      "cmsModuleService"19    )20
21    const cmsBrands = await cmsModuleService.createBrands(brands)22
23    return new StepResponse(cmsBrands, cmsBrands)24  },25  async (brands, { container }) => {26    const cmsModuleService = container.resolve(27      "cmsModuleService"28    )29
30    await cmsModuleService.deleteBrands(31      brands.map((brand) => brand.id)32    )33  }34)

The retrieveBrandsStep retrieves the brands from a brand module, and the createBrandsInCmsStep creates the brands in a third-party system using a CMS module.

Then, create the following workflow that uses these steps:

Example Workflow
1export const syncBrandsWorkflow = createWorkflow(2  "sync-brands",3  () => {4    const brands = retrieveBrandsStep()5
6    createBrandsInCmsStep({ brands })7  }8)

You can then use this workflow in an API route, scheduled job, or other resources that use this functionality.

Was this chapter helpful?
Edit this page