3.9. Events and Subscribers

In this chapter, you’ll learn how to handle events with subscribers.

What is an Event?#

When an action is performed in Medusa, such as creating a product, the Medusa application emits an event. You can listen to those events and perform an asynchronous action.

What is a Subscriber?#

A subscriber is a function executed whenever the event it listens to is emitted.

How to Create a Subscriber?#

A subscriber is created in a TypeScript or JavaScript file under the src/subscribers directory.

For example, create the file src/subscribers/product-created.ts with the following content:

1import { type SubscriberConfig } from "@medusajs/medusa"2
3// subscriber function4export default async function productCreateHandler() {5  console.log("A product was created")6}7
8// subscriber config9export const config: SubscriberConfig = {10  event: "product.created",11}

A subscriber file must export:

  • A subscriber function that is an asynchronous function executed whenever the associated event is triggered.
  • A configuration object defining the event this subscriber is listening to.

The above subscriber listens to the product.created event. Whenever the event is emitted, it logs in the terminal A product is created.

Test the Subscriber#

To test the subscriber, start the Medusa application:

Then, go to the Medusa Admin at localhost:9000/app and create a product. You’ll see the following messages logged in the Medusa application's terminal:

1info:    Processing product.created which has 1 subscribers2A product was created

The first message indicates that the product.created event was emitted, and the second one is the message logged from the subscriber.

When to Use Subscribers#

Use subscribers when
  • You want to perform an action everytime a specific event is emitted in the Medusa application.

Resolve Resources#

The subscriber function accepts an object parameter with the property container. Its value is the Medusa container, and you can use it to resolve other resources, such as services.

For example:

1import { SubscriberArgs, type SubscriberConfig } from "@medusajs/medusa"2import { IProductModuleService } from "@medusajs/types"3import { ModuleRegistrationName } from "@medusajs/utils"4
5export default async function productCreateHandler({6  data,7  container,8}: SubscriberArgs<{ id: string }>) {9  const productModuleService: IProductModuleService =10    container.resolve(ModuleRegistrationName.PRODUCT)11
12  const productId = data.data.id13
14  const product = await productModuleService.retrieveProduct(15    productId16  )17
18  console.log(`The product ${product.title} was created`)19}20
21export const config: SubscriberConfig = {22  event: `product.created`,23}

You use the container to resolve the Product Module's main service, then log the title of the created product.

Was this chapter helpful?