Motia Icon
Core Concepts

Overview

Build production-grade backends with a single primitive - APIs, background jobs, workflows, and AI agents unified

Build production-grade backends with a single primitive.

Motia is a unified backend framework that combines APIs, background jobs, durable workflows, AI agents, streaming, and observability around one core primitive: the Step.

Want an API? That's a Step. Need a background job? That's a Step. Scheduled task? Also a Step.

Write each Step in whatever language makes sense — TypeScript, Python, or JavaScript. Each language runtime runs independently, managed by the iii engine, and they all share the same state and communicate through queued messages.

How It Works

Every Step is just a file with two parts:

1. Config → When and how it runs 2. Handler → What it does

src/my-step.step.ts
import { type Handlers, type StepConfig } from 'motia'
 
export const config = {
  name: 'MyStep',
  description: 'Handles incoming requests',
  triggers: [
    { type: 'http', path: '/endpoint', method: 'POST' },
  ],
  enqueues: ['task.done'],
  flows: ['my-flow'],
} as const satisfies StepConfig
 
export const handler: Handlers<typeof config> = async (req, { enqueue, logger }) => {
  logger.info('Processing request')
 
  await enqueue({
    topic: 'task.done',
    data: { result: 'success' }
  })
 
  return { status: 200, body: { success: true } }
}

Drop this file in your src/ folder and Motia finds it automatically. No registration, no imports, no setup.

Learn more about Steps


Event-Driven Architecture

Steps don't call each other. They enqueue messages to topics that other Steps consume.

This means:

  • Your API can trigger a background job without waiting for it
  • Steps run independently and retry on failure
  • You can add new Steps without touching existing ones
  • Everything is traceable from start to finish

Example: An API enqueues a message, a queue Step picks it up:

// API Step enqueues
await enqueue({ topic: 'user.created', data: { email } })
 
// Queue Step triggers on the topic
config = {
  triggers: [
    { type: 'queue', topic: 'user.created' }
  ]
}

That's it. No coupling, no dependencies.


Project Structure & Auto-Discovery

Motia automatically discovers Steps - no manual registration required.

Basic Structure

config.yaml
.env
package.json
requirements.txt
tsconfig.json

The src/ directory is the heart of your Motia application. All your workflow logic lives here, and Motia automatically discovers any file following the naming pattern.

Auto-Discovery Rules

Motia scans the src/ directory and automatically registers files that:

  1. Match naming pattern:

    • TypeScript: .step.ts
    • JavaScript: .step.js
    • Python: _step.py (note: underscore before step)
  2. Export a config object with Step configuration

  3. Export a handler function with business logic

No imports. No registration. Just create the file and Motia finds it.


Multi-Language Support

Every Step can be in a different language. Each language runtime runs as an independent process managed by the iii engine — Python developers do not need Node.js, and vice versa. All runtimes share the same state and communicate through the same queue infrastructure.

Currently Supported:

  • TypeScript .step.ts
  • Python _step.py (standalone motia Python package — no Node.js required)
  • JavaScript .step.js

Example project:

api-endpoint.step.ts
ml-inference_step.py
send-email.step.js

All three Steps work together. TypeScript API enqueues a message, Python processes with ML, JavaScript sends the result.


Core Concepts

State Management

Persistent key-value storage that works across all Steps and languages. state.set returns { new_value, old_value }.

const result = await state.set('users', 'user-123', { name: 'John' })
// result = { new_value: { name: 'John' }, old_value: null }
const user = await state.get('users', 'user-123')

Learn about State

Real-Time Streams

Push live updates to connected clients (browsers, mobile apps).

await streams.notifications.set('user-123', 'notif-1', {
  message: 'Order shipped!',
  timestamp: new Date().toISOString()
})

Clients receive updates instantly.

Learn about Streams

Infrastructure via config.yaml

All infrastructure — queues, state storage, streams, cron scheduling, and observability — is configured through config.yaml modules managed by the iii engine. Swap default file-based storage with Redis or RabbitMQ without changing your application code.

Learn about the iii Engine

Context Object

Every handler gets a context object with everything you need:

PropertyWhat It Does
loggerStructured logging
enqueueTrigger other Steps
statePersistent storage
streamsReal-time updates
traceIdRequest tracing

Motia + iii

Motia is the application framework — you write Steps in TypeScript, Python, or JavaScript. The iii engine is the runtime that powers everything underneath: it manages queues, state storage, stream servers, cron scheduling, HTTP routing, and observability.

You configure iii through a config.yaml file that declares which modules to load and how to configure their adapters (file-based for development, Redis/RabbitMQ for production). The iii engine then manages the lifecycle of your Motia SDK processes via the ExecModule.

Learn more about the iii Engine


Development Tool - iii Development Console

Visual interface for building and debugging flows:

  • See your entire flow as a beautiful diagram
  • Watch logs in real-time
  • Inspect state as it changes
  • View stream updates in real-time

iii Console Dashboard

Flow diagram in iii Console

Learn about the iii development console


What's Next?

On this page