Skip to main content

Services

Services in Medusa encapsulate business logic and data access. They follow the MedusaService pattern, which provides automatic transaction management, event emission, and context injection through decorators.

MedusaService Pattern

All module services extend MedusaService, which provides:
  • Automatic CRUD operations - Generated list, retrieve, create, update, delete methods
  • Transaction management - Decorators for database transactions
  • Event emission - Automatic domain event publishing
  • Context injection - Shared context across operations
  • Type safety - Strongly typed DTOs and entities
The MedusaService pattern standardizes how services are built across all Medusa modules, ensuring consistency and reducing boilerplate.

Creating a Service

Basic Service Structure

Source: packages/modules/api-key/src/services/api-key-module-service.ts:44-67

Service Type Definitions

Define entity-to-DTO mappings in the generic:
Source: packages/modules/product/src/services/product-module-service.ts:82-120

Service Decorators

Medusa provides four key decorators for cross-cutting concerns:

@InjectManager

Injects an entity manager for database operations. Use on public methods.
Always use @InjectManager() on public service methods that perform database operations. This ensures a proper entity manager is available.

@InjectTransactionManager

Injects a transaction manager for atomic operations. Use on protected methods.
Source: packages/modules/api-key/src/services/api-key-module-service.ts:69-110
Use the convention of public methods calling protected methods with a _ suffix. The public method has @InjectManager and @EmitEvents, while the protected method has @InjectTransactionManager.

@MedusaContext

Injects shared context into the decorated parameter. Always use as the last parameter.
The @MedusaContext() decorator must always be applied to the last parameter of the method, and that parameter should default to an empty object {}.

@EmitEvents

Automatically emits domain events after the method completes successfully.
Source: packages/modules/api-key/src/services/api-key-module-service.ts:123-150 Events are automatically emitted based on the entity name and operation:
  • apiKey.created - After creating API keys
  • apiKey.updated - After updating API keys
  • apiKey.deleted - After deleting API keys

Decorator Combinations

Common decorator patterns:

Transaction Management

Services handle transactions automatically through decorators:

Automatic Transactions

Manual Transactions

For complex scenarios, manually manage transactions:

Event Emission

Services emit events automatically with @EmitEvents:

Automatic Event Names

Events follow the pattern {entityName}.{operation}:

Event Data

Event data includes the entity IDs:

Subscribing to Service Events

Create subscribers to handle service events:

Context Propagation

The shared context flows through all service calls:

Custom Context Data

Add custom data to the context:

Error Handling

Services use MedusaError for consistent error handling:

Common Error Types

Source: packages/modules/api-key/src/services/api-key-module-service.ts:100-107

Best Practices

1

Use Public/Protected Pattern

Public methods have @InjectManager and @EmitEvents. Protected methods (suffixed with _) have @InjectTransactionManager.
2

Always Pass Context

Always pass sharedContext to nested service calls to maintain transaction scope.
3

Validate Early

Validate input data before starting database operations to fail fast.
4

Return Serialized DTOs

Use baseRepository_.serialize() to return properly typed DTOs.
Never access this.manager_ or this.transactionManager_ directly. Always use decorators and pass context to maintain proper transaction boundaries.

Testing Services

Services are testable through dependency injection:

Next Steps

Events

Learn how to subscribe to service events

Workflows

Use services in workflow steps