System Overview
iii uses a centralized engine + distributed worker architecture connected via WebSocket. The engine coordinates routing and discovery, while workers execute functions and manage trigger types.The engine is a single Rust process. Workers are separate processes in any language (Node.js, Python, Rust, etc.) that connect via WebSocket.
The Engine
The engine is the central orchestration hub written in Rust. It manages:- WebSocket connections from workers
- Function registry for discovering and routing calls
- Trigger registry for event-to-function mappings
- Worker registry for tracking connected workers
- Modules for built-in functionality (HTTP API, Queue, Cron, etc.)
- Invocation handling for request/response coordination
Engine Structure
DashMap, Arc<RwLock<T>>) for lock-free access.
Default Ports
| Port | Service |
|---|---|
| 49134 | WebSocket (worker connections) |
| 3111 | HTTP API |
| 3112 | Stream API (WebSocket) |
| 9464 | Prometheus metrics |
Starting the Engine
Workers
Workers are processes that connect to the engine and provide functions. Workers can be written in any language with a iii SDK.Worker Capabilities
- Register functions: Make code executable by the engine
- Register trigger types: Declare support for event sources (http, cron, etc.)
- Register triggers: Connect event sources to functions
- Invoke functions: Call other functions across the system
- Stream telemetry: Send OpenTelemetry traces, metrics, and logs
Worker Lifecycle
Worker Implementation
WebSocket Protocol
Workers and the engine communicate via JSON messages over WebSocket. The protocol is bidirectional and async.Message Types
| Message | Direction | Purpose |
|---|---|---|
WorkerRegistered | Engine → Worker | Confirm connection, provide worker ID |
RegisterFunction | Worker → Engine | Register a callable function |
UnregisterFunction | Worker → Engine | Remove a function |
RegisterTriggerType | Worker → Engine | Declare trigger type support |
RegisterTrigger | Worker → Engine | Create a trigger instance |
UnregisterTrigger | Worker → Engine | Remove a trigger |
TriggerRegistrationResult | Engine → Worker | Confirm trigger registration |
InvokeFunction | Bidirectional | Request function execution |
InvocationResult | Bidirectional | Return function result |
RegisterService | Worker → Engine | Register a logical service grouping |
Ping / Pong | Bidirectional | Keep-alive heartbeat |
Example Protocol Flow
Protocol Message Schemas
RegisterFunction
RegisterFunction
InvokeFunction
InvokeFunction
invocation_id is optional. Omit for fire-and-forget calls.InvocationResult
InvocationResult
result or error will be set, not both.RegisterTrigger
RegisterTrigger
Binary Protocol Extensions
In addition to JSON messages, iii supports binary WebSocket frames for high-performance telemetry:- OTLP prefix (
OTLP): OpenTelemetry trace spans - MTRC prefix (
MTRC): OpenTelemetry metrics - LOGS prefix (
LOGS): OpenTelemetry logs
Invocation Flow
When a function is invoked, the engine coordinates the request/response lifecycle:Same-Worker Invocation
Cross-Worker Invocation
Fire-and-Forget
Omitinvocation_id for async calls that don’t need a response:
Modules
Modules are built-in engine plugins that provide functionality. They run inside the engine process and can register functions, trigger types, and services.Default Modules
| Module | Class | Purpose |
|---|---|---|
| HTTP | RestApiModule | HTTP API server, maps routes to functions |
| Queue | QueueModule | Redis-backed pub/sub queue |
| Cron | CronModule | Distributed cron scheduling |
| Stream | StreamModule | Real-time WebSocket streaming |
| Observability | OtelModule | Telemetry collection and export |
| Shell | ExecModule | File watcher for dev workflows |
Module Configuration
Modules are configured inconfig.yaml:
Custom Modules
You can create custom modules in Rust:examples/custom_queue_adapter.rs for a complete example.
Observability
iii has built-in observability using OpenTelemetry:Distributed Tracing
All function invocations are traced with parent-child span relationships:traceparent: W3C Trace Context propagationbaggage: Cross-cutting context metadata- Automatic span creation and linking
Metrics
Engine metrics exported on:9464/metrics (Prometheus format):
iii_workers_active: Current worker countiii_workers_spawns_total: Total workers connectediii_functions_registered_total: Total functions registerediii_invocations_total: Function invocation countiii_invocation_duration_seconds: Invocation latency histogram
Logs
Structured logging withtracing:
Scalability Considerations
Horizontal Workers
Add more workers to scale function execution capacity
Single Engine
Engine is single-process, vertically scaled (multi-threaded Rust)
Function Routing
O(1) hash lookup, no coordination overhead
WebSocket Limits
Tested with 10,000+ concurrent worker connections
Security
Network Security
- Engine binds to
127.0.0.1by default (localhost only) - Configure
host: 0.0.0.0to accept external connections - Use TLS-terminating reverse proxy (Caddy, nginx) for production
Worker Authentication
Currently, worker connections are unauthenticated. For production:- Run engine behind a firewall
- Use VPN or private networking
- Implement custom auth in modules
Function Invocation Security
- HTTP functions support auth configurations (Bearer, API key)
- External functions can use
authfield for credentials - Internal function calls are trusted (no auth)
Next Steps
Functions
Learn about registering and invoking functions
Triggers
Connect event sources to functions
Configuration
Configure modules and engine settings
Development
Set up a local development environment