Workflow Hooks (Advanced)
Workflow hooks let you inject custom logic into existing Medusa workflows without recreating them. Use them to extend core commerce flows.
Note: Hooks run in-band (synchronously within the workflow). If your task can run in the background, use a subscriber instead for better performance.
Basic Hook Pattern
// src/workflows/hooks/product-created.ts
import { createProductsWorkflow } from "@medusajs/medusa/core-flows"
import { StepResponse } from "@medusajs/framework/workflows-sdk"
createProductsWorkflow.hooks.productsCreated(
// Hook handler
async ({ products, additional_data }, { container }) => {
if (!additional_data?.brand_id) {
return new StepResponse([], [])
}
const link = container.resolve("link")
// Link products to brand
const linkData = products.map((product) => ({
product: { product_id: product.id },
brand: { brand_id: additional_data.brand_id },
}))
await link.create(linkData)
return new StepResponse(linkData, linkData)
},
// Compensation (runs if workflow fails after this point)
async (linkData, { container }) => {
const link = container.resolve("link")
await link.dismiss(linkData)
}
)Common Workflow Hooks
createProductsWorkflow.hooks.productsCreated- After products are createdcreateOrderWorkflow.hooks.orderCreated- After an order is createdupdateCartPromotionsWorkflow.hooks.setPromotionContext- Inject extra context into promotion computation (v2.15.0+)upsertTaxLinesWorkflow.hooks.setTaxLineContext,updateTaxLinesWorkflow.hooks.setTaxLineContext,updateOrderTaxLinesWorkflow.hooks.setTaxLineContext- Customize the context passed to tax calculation (v2.16.0+)- Ask MedusaDocs for specific workflow hooks and their input parameters
Context hooks (setPromotionContext, setTaxLineContext) are the supported way to feed custom data into Medusa's promotion and tax calculation instead of overriding the workflows:
// src/workflows/hooks/promotion.ts
import { StepResponse } from "@medusajs/framework/workflows-sdk"
import { updateCartPromotionsWorkflow } from "@medusajs/medusa/core-flows"
updateCartPromotionsWorkflow.hooks.setPromotionContext(
({ cart }, { container }) => {
if (cart.items.length >= 2) {
return new StepResponse({ company_id: "company_123" })
}
}
)When to Use Hooks vs Subscribers
Use workflow hooks when:
- The logic must complete before the workflow finishes
- You need rollback/compensation capabilities
- The operation is critical to the workflow's success
Use subscribers when:
- The logic can run asynchronously in the background
- You don't need to block the main workflow
- Better performance is needed (hooks are synchronous)
Hook Best Practices
- Return StepResponse: Always wrap your return value
- Implement compensation: Provide rollback logic for the compensation function
- Handle missing data gracefully: Check for optional data and return early if not present
- Keep hooks lightweight: For heavy operations, consider using subscribers instead