Motia Icon
Core Concepts

Adapters

Pluggable infrastructure components that enable horizontal scaling and custom implementations

Adapters are pluggable infrastructure components that let you replace Motia's default implementations with your own. They enable horizontal scaling, custom storage backends, and production-ready deployments.

What Are Adapters?

Motia uses adapters to abstract infrastructure concerns. Instead of hardcoding file storage or in-memory queues, Motia uses adapter interfaces that you can swap out.

Four adapter types:

  • State Adapter → Persistent key-value storage (default: file-based)
  • Stream Adapter → Real-time data streams (default: file-based)
  • Event Adapter → Event-based communication (default: in-memory queue)
  • Cron Adapter → Distributed cron job locking (default: in-memory)

Why Use Adapters?

Default Adapters (No Configuration Needed)

For single-instance deployments, Motia works out of the box with default adapters:

  • FileStateAdapter → Stores state in .motia/motia.state.json
  • FileStreamAdapter → Stores streams in .motia/streams/
  • InMemoryQueueEventAdapter → Events in process memory
  • InMemoryCronAdapter → Single-instance cron locking

Default adapters are perfect for development, testing, and single-instance deployments. No configuration needed!

Distributed Adapters (For Production)

When you need to scale horizontally or run multiple instances, switch to distributed adapters:

  • Redis State Adapter → Shared state across instances
  • Redis Stream Adapter → Real-time streams across instances
  • RabbitMQ Event Adapter → Distributed event queue
  • Redis Cron Adapter → Distributed cron locking

Use distributed adapters when running multiple Motia instances. Without them, each instance has its own isolated state and events.

How Adapters Work

Adapters implement interfaces defined in @motiadev/core. Your application code doesn't change - just swap the adapter implementation.

Example: Switching from file storage to Redis

motia.config.ts
import { config } from '@motiadev/core'
import { RedisStateAdapter } from '@motiadev/adapter-redis-state'
import { RedisStreamAdapter } from '@motiadev/adapter-redis-streams'
import { RabbitMQEventAdapter } from '@motiadev/adapter-rabbitmq-events'
import { RedisCronAdapter } from '@motiadev/adapter-redis-cron'
 
export default config({
  adapters: {
    state: new RedisStateAdapter({
      host: process.env.REDIS_HOST,
      port: 6379,
    }),
    streams: new RedisStreamAdapter({
      host: process.env.REDIS_HOST,
      port: 6379,
    }),
    events: new RabbitMQEventAdapter({
      url: process.env.RABBITMQ_URL,
    }),
    cron: new RedisCronAdapter({
      host: process.env.REDIS_HOST,
      port: 6379,
    }),
  },
})

Your Step code stays exactly the same:

// This works with both file and Redis adapters
export const handler: Handlers['MyStep'] = async (req, { state, streams }) => {
  await state.set('orders', 'order-123', { id: 'order-123' })
  await streams.messages.set('chat-123', 'msg-1', { text: 'Hello' })
  // ... rest of your code
}

When to Use Custom Adapters

Use default adapters when:

  • Running a single Motia instance
  • Local development
  • Testing
  • Simple deployments

Use distributed adapters when:

  • Running multiple Motia instances
  • Need horizontal scaling
  • Production deployments
  • High availability requirements
  • Need shared state/events across instances

Available Adapters

Official Packages

  • @motiadev/adapter-redis-state - Redis-based state storage
  • @motiadev/adapter-redis-streams - Redis streams implementation
  • @motiadev/adapter-redis-cron - Redis distributed locking for cron
  • @motiadev/adapter-rabbitmq-events - RabbitMQ event handling

Default Implementations

Included in @motiadev/core (no external dependencies):

  • FileStateAdapter - File-based state (default)
  • MemoryStateAdapter - In-memory state (testing)
  • FileStreamAdapter - File-based streams (default)
  • MemoryStreamAdapter - In-memory streams (testing)
  • InMemoryQueueEventAdapter - In-memory event queue (default)
  • InMemoryCronAdapter - Single-instance cron locking (default)

Architecture

Adapters follow the interface pattern:

  1. Interfaces define contracts in @motiadev/core
  2. Implementations satisfy these contracts
  3. Composition is used throughout - adapters are injected, not extended

This design means:

  • ✅ Easy to swap implementations
  • ✅ Type-safe with full TypeScript support
  • ✅ Testable with in-memory adapters
  • ✅ Extensible for custom backends

What's Next?

Need help? See our Community Resources for questions, examples, and discussions.

On this page