Digital commerce happens across multiple systems, whether ERPs, CMSs, marketing tools, custom services, or other tools. A key challenge is to ensure these systems work together to complete the tasks that drive your business forward. We are, therefore, incredibly excited to announce the beta release of Medusa Workflows, a new, powerful primitive in the Medusa toolbox to help build custom business flows involving multiple systems.
Medusa’s Workflows SDK enables developers to write critical business flows with a simple DX and a strong foundation. Workflows have built-in retry and rollback mechanisms, which make them resilient to intermittent failures and a great place to define your commerce stack’s integrations and customizations.
Medusa Workflows are not dependent on Medusa’s commerce modules. You can start using them to integrate your commerce stack regardless of what ecommerce platform you are on, giving you access to Medusa’s powerful customization tools without needing to migrate your commerce platform.
Build a Workflow
Building Workflows is like writing JavaScript functions, but unlike regular functions, the Workflows SDK creates an internal representation of your Workflow to keep track of its progress, retry failing steps, and roll back operations if necessary.
Define a Workflow Step
To create a Workflow, you first define a Workflow Step using the Workflows SDK’s Copy to clipboardcreateStep
function.
12345678import { createStep, StepResponse } from "@medusajs/workflows-sdk"const reserveInventory = createStep("reserve-inventory", async (cart, context) => {const inventoryService = context.container.resolve("inventoryService");await inventoryService.reserveInventory(cart.items);return new StepResponse({ success: true });});
The above step resolves an Inventory Service from the dependency injection container and reserves inventory for items in a Cart. Note that the step takes a Cart as input and responds with a StepResponse. The StepResponse can be used in subsequent steps.
Create a Workflow
Once your step is created, you can use it within a Workflow. To construct a Workflow you use the Copy to clipboardcreateWorkflow
helper from the Workflows SDK.
1234567891011121314import { createStep, StepResponse, createWorkflow } from "@medusajs/workflows-sdk"const reserveInventory = createStep("reserve-inventory", async (cart, context) => {const inventoryService = context.container.resolve("inventoryService");await inventoryService.reserveInventory(cart.items);return new StepResponse({ success: true });});const acceptQuoteWorkflow = createWorkflow("accept-quote", function (input) {const cart = retrieveCart(input.cartQuoteId);reserveInventory(cart);authorizePayment(cart);createOrder(cart);});
The above Workflow accepts a quote shared with a customer, and the step we created to reserve inventory is used as part of the Workflow. In the Workflow, we have used our Copy to clipboardreserveInventory
Workflow Step.
The function passed to Copy to clipboardcreateWorkflow
is used to generate a representation of the Workflow logic and map the data dependencies between steps. For example, the Workflow SDK knows that Copy to clipboardreserveInventory
step needs the output of Copy to clipboardretrieveCart
as its input. This enables Medusa to automatically retry a step if it fails and only progress when possible and allowed. If a step fails more than a configurable number of times, Medusa will automatically roll back previous steps.
Defining compensating actions
Let’s define the compensation for our Copy to clipboardreserveInventory
step. We do this by specifying what data our step will need to roll back in the StepResponse and a compensation function to execute when rolling back.
123456789101112import { createStep, StepResponse } from "@medusajs/workflows-sdk"const reserveInventory = createStep("reserve-inventory", async (cart, context) => {const inventoryService = context.container.resolve("inventoryService");await inventoryService.reserveInventory(cart.items);return new StepResponse({ success: true }, cart.items);},async (items, context) => {const inventoryService = context.container.resolve("inventoryService");await inventoryService.releaseInventory(items);});
Note that the StepResponse now specifies the Copy to clipboardcart.items
as rollback data. This is then used in the compensation function to release the inventory.
Triggering a Workflow
You can execute a Workflow from different places within Medusa. For example, you may use API Routes if you want the workflow to execute in response to an API request or a webhook. Subscribers if you want to execute a workflow when an event is triggered. Or Scheduled Jobs if you want your workflow to execute regularly.
Here’s an example of executing a Workflow in an API Route. You can learn about more ways of triggering Workflows in our docs.
12345678910111213// src/api/quotes/accept/route.tsimport { acceptQuoteWorkflow } from "@/workflows"export async function POST(req, res) {const workflow = acceptQuoteWorkflow(req.scope)await workflow.run({cartQuoteId: req.cart_id})res.json({ accepted: true })}
What can you use Workflows for?
Medusa Workflows are especially good for orchestrating multiple tools to achieve a task. Integrating systems in your stack using Workflows, for example, ensures that data is kept consistent and that unexpected errors are handled gracefully. To build an integration with Workflows, you would create a custom Medusa service connecting to your 3rd party system. The custom service can then be resolved in your steps to execute actions.
The more systems you integrate with Medusa, the more Workflows you can create to automate your operations and push your customer experience forward. Consider the example of integrating purchase orders from your ERP system with inbounds in your WMS system. With a Medusa connection to your ERP and WMS, you can easily map the purchase order flow and other ERP to WMS flows. Additionally, because you have other connections - like your product information - available, you can leverage those in your Workflows. For example, you can quickly configure your purchase order Workflow to record the expected restock date of your products to display to customers.
Long-running workflows (coming soon)
With the initial beta release, Workflows can run exclusively in-band. We will soon add support for long-running Workflows that include asynchronous operations or human-in-the-loop steps. This opens further use cases for Workflows. For example, you can build a Workflow to manage the preparation of new products for sale. The Workflow starts when a product is inbounded at your warehouse. Then, tasks can kick off for taking pack shots, writing titles and descriptions, translating copy, and merchandizing the product. As each task is completed, the Workflow can proceed. All tasks would be mapped as Workflow Steps and could be completed in systems across your stack. If a task fails to complete or a configurable timeout is reached, rollback logic can help keep your data consistent, or notify responsible parties.
Core Workflows
Workflows are a key part of our efforts toward shipping Medusa 2.0. With Medusa 2.0, we are decoupling most of Medusa’s internal services and bringing them to standalone packages available on npm. This means you can use Medusa’s services, like Products, Pricing, Carts, etc., independently from the rest of Medusa. We will continue to offer Medusa’s powerful and customizable commerce API in a way that’s easy to install with Copy to clipboardnpx create-medusa-app
. For each default API endpoint, there will be an available core Workflow to do things like creating products, adding to cart, applying discounts, and much, much more. The core Workflows will orchestrate Medusa (or custom) modules and be extensible. This does two things:
- It makes Medusa pluggable - you can use any provider to handle Products, Carts, Discounts, etc. The Workflow will call the provider when it needs to.
- You will get a new and easy way to extend business logic by injecting custom code into Workflows. There is no need to modify core services or override default endpoints; the Workflow will ensure your custom logic is called when required.
Core Workflows are introduced incrementally behind the Copy to clipboardmedusa_v2
feature flag, and more and more Workflows become available as we ship new Commerce Modules.
What’s next?
The Workflows SDK joins Custom Entities, Services, API Routes, Subscribers, and Cron Jobs in the Medusa toolbox. With Workflows, Medusa provides a primitive for building custom business flows spanning multiple systems. It has built-in failure handling and rollback logic to ensure your critical Workflows run smoothly and your data is kept consistent. You can start using the Workflows SDK without migrating to Medusa’s commerce modules, making it an excellent tool for integrating your digital commerce stack and building customizations for customer experiences and internal operations.
Visit our docs to get started with Workflows. And follow us on X to stay tuned for updates on Long Running Workflows and information about our Commerce Module releases as we prepare for Medusa 2.0.