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:
- Current working directory
/app/config.yaml (in Docker)
- 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:
| Field | Type | Default | Description |
|---|
host | string | 127.0.0.1 | Bind address |
port | number | 3111 | HTTP port |
default_timeout | number | 30000 | Request timeout (ms) |
concurrency_request_limit | number | 1024 | Max concurrent requests |
cors.allowed_origins | array | ['*'] | CORS allowed origins |
cors.allowed_methods | array | [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:
| Field | Type | Description |
|---|
adapter.class | string | Adapter implementation |
adapter.config.redis_url | string | Redis 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:
| Field | Type | Default | Description |
|---|
store_method | string | in_memory | Storage backend: in_memory or file_based |
file_path | string | - | File path for file_based storage |
save_interval_ms | number | 5000 | How 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