Skip to main content

Configuration File

Motia uses a YAML configuration file (typically config.yaml or iii-config.yaml) to define which modules to load and how to configure them.

File Location

By default, the engine looks for config.yaml in:
  1. Current working directory
  2. /app/config.yaml (in Docker)
  3. Specified via --config flag:
iii --config /path/to/config.yaml

Basic Structure

modules:
  - class: modules::api::RestApiModule
    config:
      port: 3111
      host: 127.0.0.1
  
  - class: modules::cron::CronModule
    config:
      adapter:
        class: modules::cron::KvCronAdapter
Each module is defined with:
  • class: Rust module path
  • config: Module-specific configuration object

Environment Variable Expansion

Configuration files support environment variable expansion with default values:
modules:
  - class: modules::stream::StreamModule
    config:
      port: ${STREAM_PORT:3112}
      adapter:
        config:
          redis_url: ${REDIS_URL:redis://localhost:6379}
Syntax:
  • ${VAR_NAME}: Required variable (fails if not set)
  • ${VAR_NAME:default}: Optional with default value

Available Modules

REST API Module

Exposes HTTP endpoints for registered functions.
modules:
  - class: modules::api::RestApiModule
    config:
      host: 127.0.0.1        # Bind address (use 0.0.0.0 for all interfaces)
      port: 3111             # HTTP port
      default_timeout: 30000 # Request timeout in milliseconds
      concurrency_request_limit: 1024  # Max concurrent requests
      cors:
        allowed_origins:
          - '*'              # CORS origins (use specific domains in prod)
        allowed_methods:
          - GET
          - POST
          - PUT
          - DELETE
          - OPTIONS
Configuration Options:
FieldTypeDefaultDescription
hoststring127.0.0.1Bind address
portnumber3111HTTP port
default_timeoutnumber30000Request timeout (ms)
concurrency_request_limitnumber1024Max concurrent requests
cors.allowed_originsarray['*']CORS allowed origins
cors.allowed_methodsarray[GET, POST, ...]CORS allowed methods

Stream Module

Real-time state synchronization over WebSocket.
modules:
  - class: modules::stream::StreamModule
    config:
      port: ${STREAM_PORT:3112}
      host: 127.0.0.1
      adapter:
        class: modules::stream::adapters::RedisAdapter
        config:
          redis_url: redis://localhost:6379
Adapters: RedisAdapter (production recommended):
adapter:
  class: modules::stream::adapters::RedisAdapter
  config:
    redis_url: ${REDIS_URL:redis://localhost:6379}
KvStore (development only):
adapter:
  class: modules::stream::adapters::KvStore
  config:
    store_method: file_based  # Options: in_memory, file_based
    file_path: ./data/stream_store

Queue Module

Redis-backed publish/subscribe message queue.
modules:
  - class: modules::queue::QueueModule
    config:
      adapter:
        class: modules::queue::RedisAdapter
        config:
          redis_url: redis://localhost:6379
Configuration Options:
FieldTypeDescription
adapter.classstringAdapter implementation
adapter.config.redis_urlstringRedis connection string

Cron Module

Distributed cron scheduling with lock coordination.
modules:
  - class: modules::cron::CronModule
    config:
      adapter:
        class: modules::cron::KvCronAdapter
The cron module uses the KV store for distributed locking, preventing duplicate executions across multiple engine instances.

KV Server Module

Key-value storage with file or memory backend.
modules:
  - class: modules::kv_server::KvServer
    config:
      store_method: file_based  # Options: in_memory, file_based
      file_path: ./data/kv_store
      save_interval_ms: 5000     # Persistence interval for file_based
Configuration Options:
FieldTypeDefaultDescription
store_methodstringin_memoryStorage backend: in_memory or file_based
file_pathstring-File path for file_based storage
save_interval_msnumber5000How often to persist to disk (ms)

State Module

Persistent state storage for workers.
modules:
  - class: modules::state::StateModule
    config:
      adapter:
        class: modules::state::adapters::KvStore
        config:
          store_method: file_based
          file_path: ./data/state_store.db

PubSub Module

Publish/subscribe messaging.
modules:
  - class: modules::pubsub::PubSubModule
    config:
      adapter:
        class: modules::pubsub::LocalAdapter
Adapters:
  • LocalAdapter: In-process pub/sub (single engine instance)
  • RedisAdapter: Redis-backed pub/sub (distributed)

Observability Module

OpenTelemetry tracing, metrics, and logging.
modules:
  - class: modules::observability::OtelModule
    config:
      # Core Configuration
      enabled: ${OTEL_ENABLED:true}
      service_name: ${OTEL_SERVICE_NAME:iii}
      service_version: ${SERVICE_VERSION:0.2.0}
      service_namespace: ${SERVICE_NAMESPACE:production}
      
      # Trace Exporter
      exporter: ${OTEL_EXPORTER_TYPE:memory}  # Options: otlp, memory, both
      endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT:http://localhost:4317}
      
      # Sampling
      sampling_ratio: 1.0  # 0.0 to 1.0 (1.0 = 100%)
      
      # Memory Storage
      memory_max_spans: ${OTEL_MEMORY_MAX_SPANS:10000}
      
      # Metrics
      metrics_enabled: true
      metrics_exporter: ${OTEL_METRICS_EXPORTER:memory}  # Options: memory, otlp
      metrics_retention_seconds: 3600
      metrics_max_count: 10000
      
      # Logs
      logs_enabled: ${OTEL_LOGS_ENABLED:true}
      logs_exporter: ${OTEL_LOGS_EXPORTER:memory}  # Options: memory, otlp, both
      logs_max_count: ${OTEL_LOGS_MAX_COUNT:1000}
      logs_retention_seconds: ${OTEL_LOGS_RETENTION_SECONDS:3600}
      logs_batch_size: ${OTEL_LOGS_BATCH_SIZE:100}
      logs_flush_interval_ms: ${OTEL_LOGS_FLUSH_INTERVAL_MS:5000}
      logs_sampling_ratio: ${OTEL_LOGS_SAMPLING_RATIO:1.0}
      logs_console_output: ${OTEL_LOGS_CONSOLE_OUTPUT:true}
Advanced Sampling: For fine-grained control, use rule-based sampling:
sampling:
  default: 0.1  # 10% default sampling
  parent_based: true
  
  rules:
    # Low sampling for health checks
    - operation: "health.*"
      rate: 0.01
    
    # High sampling for critical endpoints
    - operation: "api.critical.*"
      rate: 1.0
    
    # Service-specific rules
    - service: "payment-*"
      rate: 1.0
    
    # Combined rules
    - operation: "api.*"
      service: "production-*"
      rate: 0.8
  
  # Rate limiting
  rate_limit:
    max_traces_per_second: 100
Alert Rules:
alerts:
  - name: high_error_rate
    metric: iii.invocations.error
    threshold: 100
    operator: ">"  # Options: >, >=, <, <=, ==, !=
    window_seconds: 60
    cooldown_seconds: 300
    action: log  # Options: log, webhook, function
  
  - name: low_workers
    metric: iii.workers.active
    threshold: 1
    operator: "<"
    action: webhook
    webhook_url: https://hooks.slack.com/services/xxx

Configuration Examples

Minimal (No Dependencies)

modules:
  - class: modules::api::RestApiModule
    config:
      host: 127.0.0.1
      port: 3111
  
  - class: modules::observability::OtelModule
    config:
      enabled: false

Development (Full Stack)

modules:
  - class: modules::stream::StreamModule
    config:
      port: ${STREAM_PORT:3112}
      host: 127.0.0.1
      adapter:
        class: modules::stream::adapters::RedisAdapter
        config:
          redis_url: redis://localhost:6379

  - class: modules::kv_server::KvServer
    config:
      store_method: file_based
      file_path: ./data/kv_store
      save_interval_ms: 5000

  - class: modules::state::StateModule
    config:
      adapter:
        class: modules::state::adapters::KvStore
        config:
          store_method: file_based
          file_path: ./data/state_store.db

  - class: modules::api::RestApiModule
    config:
      port: 3111
      host: 127.0.0.1
      default_timeout: 30000
      concurrency_request_limit: 1024
      cors:
        allowed_origins:
          - '*'
        allowed_methods:
          - GET
          - POST
          - PUT
          - DELETE
          - OPTIONS

  - class: modules::observability::OtelModule
    config:
      enabled: true
      service_name: iii
      exporter: memory
      sampling_ratio: 1.0

  - class: modules::queue::QueueModule
    config:
      adapter:
        class: modules::queue::RedisAdapter
        config:
          redis_url: redis://localhost:6379

  - class: modules::pubsub::PubSubModule
    config:
      adapter:
        class: modules::pubsub::LocalAdapter

  - class: modules::cron::CronModule
    config:
      adapter:
        class: modules::cron::KvCronAdapter

Production (Minimal)

modules:
  - class: modules::api::RestApiModule
    config:
      host: 0.0.0.0
      port: 3111

  - class: modules::cron::CronModule

  - class: modules::observability::LoggingModule
    config:
      level: info
      format: json

Production (Full Stack)

modules:
  - class: modules::api::RestApiModule
    config:
      host: 0.0.0.0
      port: 3111
      default_timeout: 30000
      concurrency_request_limit: 1024
      cors:
        allowed_origins:
          - https://your-app.com
        allowed_methods:
          - GET
          - POST
          - PUT
          - DELETE
          - OPTIONS

  - class: modules::stream::StreamModule
    config:
      port: 3112
      host: 0.0.0.0
      adapter:
        class: modules::stream::adapters::RedisAdapter
        config:
          redis_url: ${REDIS_URL}

  - class: modules::queue::QueueModule
    config:
      adapter:
        class: modules::queue::RedisAdapter
        config:
          redis_url: ${REDIS_URL}

  - class: modules::cron::CronModule

  - class: modules::observability::OtelModule
    config:
      enabled: true
      service_name: ${OTEL_SERVICE_NAME:iii}
      service_version: ${SERVICE_VERSION:1.0.0}
      service_namespace: production
      exporter: otlp
      endpoint: ${OTEL_EXPORTER_OTLP_ENDPOINT}
      sampling_ratio: 0.1
      metrics_enabled: true
      metrics_exporter: otlp
      logs_enabled: true
      logs_exporter: otlp
      logs_console_output: false

Validation

The engine validates configuration on startup. Common errors: Missing required field:
error: module config validation failed: missing field 'redis_url'
Invalid module class:
error: unknown module class: modules::invalid::Module
Port already in use:
error: failed to bind to 0.0.0.0:3111: address already in use

Hot Reload

The engine does not support hot reloading of configuration. Restart the engine to apply changes.
Restart gracefully:
# Docker Compose
docker compose restart iii

# Kubernetes
kubectl rollout restart deployment/iii

# Systemd
sudo systemctl restart iii

Next Steps

Modules Reference

Learn about each module in detail

Environment Variables

Production environment configuration

Build docs developers (and LLMs) love