# Medusa Transaction Management for API Operations: How the Decorator Pattern Ensures Data Consistency

> Discover how Medusa ensures ACID compliance for API operations. Learn about automatic transaction management using the @InjectTransactionManager decorator to maintain data consistency.

- Repository: [Medusa/medusa](https://github.com/medusajs/medusa)
- Tags: internals
- Published: 2026-05-19

---

**Medusa guarantees ACID compliance for all API mutations by automatically wrapping service-layer database operations in transactions using the `@InjectTransactionManager` decorator and a shared context propagation mechanism.**

The Medusa open-source commerce framework provides robust transaction management capabilities that ensure data consistency across API operations. By leveraging the `@InjectTransactionManager` decorator and a `sharedContext` propagation pattern, Medusa automatically wraps every write operation in an atomic database transaction. This architecture prevents partial data writes and maintains referential integrity throughout the request lifecycle.

## Core Transaction Management Architecture

### The @InjectTransactionManager Decorator

At the heart of Medusa's transaction management strategy lies the **`@InjectTransactionManager`** decorator. When applied to a service method, this decorator intercepts the call to extract a transaction manager from the `sharedContext` parameter. If no transaction exists, it initializes a new one automatically. The decorator then injects the manager as the first argument (typically named `manager`) to the service method, ensuring all subsequent ORM calls execute within the same transactional boundary.

According to the Medusa source code, this pattern appears consistently across virtually every module. In [`packages/modules/store/src/services/store-module-service.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/store/src/services/store-module-service.ts) (lines 82, 121, 194), the decorator wraps mutation methods to guarantee atomic updates to store configurations and related entities.

### SharedContext Propagation Pattern

The **`sharedContext`** (or `Context`) object serves as the transaction carrier that propagates from API controllers through to service layers. When an API route receives a request, Medusa initializes a context containing a reference to the current transaction manager. This context passes through method signatures as an optional parameter (typically `sharedContext?: Context`), allowing downstream services to participate in the same database transaction without explicit transaction handling code.

In [`packages/modules/product/src/services/product-module-service.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/product/src/services/product-module-service.ts) (lines 367-424), service methods accept this shared context, enabling complex product updates—including variants, options, and inventory associations—to commit or rollback as a single atomic unit.

## How Request-Level Transactions Work

Medusa implements **request-level transaction scoping** to ensure complete operation isolation:

1. **Context Initialization** – When an API endpoint receives a mutation request, the framework creates a `Context` object containing a fresh transactional `EntityManager` (or Knex equivalent).

2. **Propagation Chain** – The controller passes this context to service methods via the `sharedContext` parameter, creating a chain of operations that share the same transactional scope.

3. **Decorated Execution** – Service methods marked with `@InjectTransactionManager` receive the transaction manager automatically, as seen in [`packages/modules/promotion/src/services/promotion-module.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/promotion/src/services/promotion-module.ts), where complex promotional rule updates require multi-table consistency.

4. **Atomic Commit** – Upon successful completion of all operations, the transaction commits automatically. If any operation fails, the entire transaction rolls back, leaving the database unchanged.

## Automatic Rollback and Error Handling

Medusa's transaction management provides **automatic rollback protection** without requiring explicit try-catch blocks in business logic. When an exception bubbles out of a method decorated with `@InjectTransactionManager`, the underlying Data Access Layer (DAL) catches the error and triggers a full transaction rollback. This behavior mirrors standard ORM transaction scopes while abstracting the complexity from service implementations.

The rollback mechanism ensures that partially completed operations—such as creating a product but failing to associate its variants—never leave the database in an inconsistent state. All related tables revert to their pre-operation condition automatically.

## Advanced Patterns: Manual Transaction Sharing

For complex business logic spanning multiple services, Medusa supports **explicit transaction sharing** through manual transaction initialization.

Advanced callers can initiate transactions via the repository's `manager.transaction` API or the `TransactionManager.startTransaction()` utility, then forward the resulting transaction manager through the `sharedContext` to subsequent service calls. This approach allows multiple discrete service methods to participate in a single atomic operation, maintaining consistency across module boundaries.

## Distributed Transactions with the Workflow Engine

For long-running or multi-step operations that extend beyond a single request lifecycle, Medusa employs the **workflow engine** (specifically `workflow-engine-redis`) to provide distributed transaction capabilities.

As defined in [`packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts), the engine implements `DistributedTransactionType` with checkpoint handling and compensation logic. This system records transaction progress at each workflow step, enabling rollback of partially completed distributed operations if subsequent steps fail. The workflow engine effectively extends ACID guarantees to complex business processes that span multiple services, external APIs, or time-delayed operations.

## Practical Implementation Examples

### Basic API Controller with Automatic Transactions

```typescript
import { ProductModuleService } from "@medusajs/modules-product"

class MyController {
  constructor(private readonly productService: ProductModuleService) {}

  async updateProduct(productId: string, data: UpdateProductDTO) {
    // The service method is decorated with @InjectTransactionManager,
    // so any DB writes are wrapped in a single transaction.
    await this.productService.update(productId, data, {
      // Passing the empty Context tells Medusa to start a new transaction.
      sharedContext: {}
    })
  }
}

```

### Manual Transaction Coordination Across Services

```typescript
import { TransactionManager } from "@medusajs/framework/utils"
import { ProductModuleService } from "@medusajs/modules-product"
import { InventoryModuleService } from "@medusajs/modules-inventory"

async function createProductWithInventory(
  productData: CreateProductDTO,
  inventoryData: CreateInventoryDTO
) {
  // Open a transaction manually
  const transaction = await TransactionManager.startTransaction()

  const ctx: Context = { transactionManager: transaction }

  // All service calls receive the same `sharedContext`
  await productService.create(productData, { sharedContext: ctx })
  await inventoryService.create(inventoryData, { sharedContext: ctx })

  // Commit the transaction once all steps succeed
  await transaction.commit()
}

```

### Workflow Step with Compensation Support

```typescript
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"

export const deleteProductStep = createStep(
  "delete-product",
  async (ids: string[], { container }) => {
    const productService = container.resolve("productModuleService")
    // The service method below is decorated with @InjectTransactionManager
    await productService.softDelete(ids, {})
    return new StepResponse(void 0, ids)
  },
  // Compensation step – restores products if the workflow rolls back
  async (idsToRestore, { container }) => {
    if (!idsToRestore?.length) return
    const productService = container.resolve("productModuleService")
    await productService.restore(idsToRestore, {})
  }
)

```

## Summary

- Medusa implements transaction management through the **`@InjectTransactionManager`** decorator, which automatically injects transactional managers into service methods.
- The **`sharedContext`** object propagates transaction state from API controllers through service layers, ensuring all operations within a request share the same transactional scope.
- **Automatic rollback** occurs when exceptions bubble out of decorated methods, preventing partial database updates without requiring explicit error handling.
- **Manual transaction sharing** allows advanced use cases to coordinate atomic operations across multiple services using `TransactionManager.startTransaction()`.
- The **workflow engine** extends transaction guarantees to distributed, long-running processes through checkpoint tracking and compensation logic as implemented in [`packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts).
- Real-world implementations in [`packages/modules/product/src/services/product-module-service.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/product/src/services/product-module-service.ts) and [`packages/modules/store/src/services/store-module-service.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/store/src/services/store-module-service.ts) demonstrate consistent application of these patterns across the codebase.

## Frequently Asked Questions

### What is the @InjectTransactionManager decorator in Medusa?

The `@InjectTransactionManager` decorator is a core framework utility that intercepts service method calls to inject a transactional database manager as the first argument. It extracts the transaction manager from the `sharedContext` parameter or creates a new transaction if none exists, ensuring all database operations within the method execute atomically. This pattern appears throughout Medusa's module services, including [`packages/modules/product/src/services/product-module-service.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/product/src/services/product-module-service.ts) and the store module service.

### How does Medusa handle transaction rollback when an API operation fails?

Medusa handles rollbacks automatically through its Data Access Layer when exceptions propagate out of methods decorated with `@InjectTransactionManager`. If any database operation fails within a transactional method, the framework catches the exception and triggers a complete rollback of all changes made within that transaction scope. This guarantees that the database remains consistent without requiring explicit rollback commands in business logic.

### Can I share transactions across multiple service calls in Medusa?

Yes, Medusa supports explicit transaction sharing across multiple service calls by manually initializing a transaction via `TransactionManager.startTransaction()` and passing the resulting manager through the `sharedContext` parameter to subsequent service methods. This approach ensures that operations spanning multiple services—such as creating a product and simultaneously updating inventory levels—commit or rollback as a single atomic unit.

### Does Medusa support distributed transactions for long-running workflows?

Yes, Medusa supports distributed transactions through its workflow engine (specifically `workflow-engine-redis`), which implements checkpoint persistence and compensation patterns defined in [`packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts`](https://github.com/medusajs/medusa/blob/main/packages/modules/workflow-engine-redis/src/utils/workflow-orchestrator-storage.ts). The engine tracks transaction state across workflow steps and can execute compensation functions to rollback completed steps if later operations fail, providing ACID-like guarantees for complex, multi-step business processes that extend beyond single request boundaries.