You start building a backend and immediately need six different tools: an API framework, a task queue, a cron scheduler, pub/sub, a state store, and an observability pipeline. Each has its own config, its own deployment, its own failure modes. A simple "process this, then notify that" workflow touches three services before you write any business logic.
iii replaces all of that with a single engine and two primitives: Function and Trigger.
A Function is anything that does work. A Trigger is what causes it to run - an HTTP request, a cron schedule, a queue message, a state change. You write the function, declare what triggers it, and the engine handles discovery, routing, retries, and observability.
One config file. One process. Everything discoverable. Think of it the way React gave frontend a single model for UI - iii gives your backend a single model for execution.
| Concept | What it does |
|---|---|
| Function | A unit of work. It receives input and optionally returns output. It can exist anywhere: locally, in the cloud, on serverless, or as a third-party HTTP endpoint. It can mutate state, invoke other functions, and modify databases. |
| Trigger | What causes a Function to run - explicitly from code, or automatically from an event source. Examples: HTTP route, cron schedule, queue topic, state change, stream event. |
| Discovery | Functions and triggers register and deregister themselves without configuration. Once discovered, they are available across the entire backend. |
curl -fsSL https://install.iii.dev/iii/main/install.sh | shThis installs both the engine and iii-cli.
Override install directory or pin a version
curl -fsSL https://install.iii.dev/iii/main/install.sh | BIN_DIR=$HOME/.local/bin shcurl -fsSL https://install.iii.dev/iii/main/install.sh | sh -s -- v0.7.0Verify:
command -v iii && iii --versioniii-cli startOpen the console:
iii-cli consoleYour engine is running at ws://localhost:49134 with HTTP API at http://localhost:3111.
npm install iii-sdkimport { init } from 'iii-sdk';
const iii = init('ws://localhost:49134');
iii.registerFunction({ id: 'math.add' }, async (input) => {
return { sum: input.a + input.b };
});
iii.registerTrigger({
type: 'http',
function_id: 'math.add',
config: { api_path: 'add', http_method: 'POST' },
});Python
pip install iii-sdkimport asyncio
from iii import init
async def main():
iii = init("ws://localhost:49134")
async def add(data):
return {"sum": data["a"] + data["b"]}
iii.register_function("math.add", add)
iii.register_trigger(
type="http",
function_id="math.add",
config={"api_path": "add", "http_method": "POST"}
)
asyncio.run(main())Rust
use iii_sdk::{init, InitOptions};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let iii = init("ws://127.0.0.1:49134", InitOptions::default())?;
iii.register_function("math.add", |input| async move {
let a = input.get("a").and_then(|v| v.as_i64()).unwrap_or(0);
let b = input.get("b").and_then(|v| v.as_i64()).unwrap_or(0);
Ok(json!({ "sum": a + b }))
});
iii.register_trigger("http", "math.add", json!({
"api_path": "add",
"http_method": "POST"
}))?;
Ok(())
}Your function is now live at http://localhost:3111/add.
The iii-console is a developer and operations dashboard for inspecting functions, triggers, traces, and real-time state. Launch it with:
iii-cli console| Module | Class | What it does | Default |
|---|---|---|---|
| HTTP API | RestApiModule |
Maps HTTP routes to functions via http triggers with CORS |
Yes |
| Queue | QueueModule |
Message queue with pluggable adapters (built-in, Redis, RabbitMQ) | Yes |
| Cron | CronModule |
Scheduled job execution with cron expression triggers | Yes |
| Stream | StreamModule |
Real-time bidirectional streaming over WebSocket | Yes |
| Pub/Sub | PubSubModule |
Topic-based event publishing and subscription | Yes |
| State | StateModule |
Distributed state management with get/set/delete and state triggers | Yes |
| KV Server | KvServer |
Built-in key-value store used by other modules | Yes |
| HTTP Functions | HttpFunctionsModule |
Proxy for invoking external HTTP endpoints as functions | No |
| Observability | OtelModule |
OpenTelemetry traces, metrics, and logs with OTLP export | No |
| Shell | ExecModule |
File watcher that runs shell commands on change | No |
If config.yaml is missing, the engine loads all default modules. Queue and Stream adapters fall back to the built-in KV store; add Redis for production use.
| Language | Package | Install |
|---|---|---|
| Node.js | iii-sdk |
npm install iii-sdk |
| Python | iii-sdk |
pip install iii-sdk |
| Rust | iii-sdk |
Add to Cargo.toml |
docker pull iiidev/iii:latest
docker run -p 3111:3111 -p 49134:49134 \
-v ./config.yaml:/app/config.yaml:ro \
iiidev/iii:latestProduction (hardened)
docker run --read-only --tmpfs /tmp \
--cap-drop=ALL --cap-add=NET_BIND_SERVICE \
--security-opt=no-new-privileges:true \
-v ./config.yaml:/app/config.yaml:ro \
-p 3111:3111 -p 49134:49134 -p 3112:3112 -p 9464:9464 \
iiidev/iii:latestDocker Compose (full stack with Redis + RabbitMQ):
docker compose up -dDocker Compose with Caddy (TLS reverse proxy):
docker compose -f docker-compose.prod.yml up -dSee the Caddy documentation for TLS and reverse proxy configuration.
| Port | Service |
|---|---|
| 49134 | WebSocket (worker connections) |
| 3111 | HTTP API |
| 3112 | Stream API |
| 9464 | Prometheus metrics |
Config files support environment expansion: ${REDIS_URL:redis://localhost:6379}.
Minimal config (no Redis required):
modules:
- class: modules::api::RestApiModule
config:
host: 127.0.0.1
port: 3111
- class: modules::observability::OtelModule
config:
enabled: false
level: info
format: defaultThe engine speaks JSON messages over WebSocket. Key message types:
registerfunction, invokefunction, invocationresult,
registertrigger, unregistertrigger, triggerregistrationresult, registerservice,
functionsavailable, ping, pong.
Invocations can be fire-and-forget by omitting invocation_id.
src/main.rs– CLI entrypoint (iiibinary)src/engine/– Worker management, routing, and invocation lifecyclesrc/protocol.rs– WebSocket message schemasrc/modules/– Core modules (API, queue, cron, stream, observability, shell)config.yaml– Example module configurationexamples/custom_queue_adapter.rs– Custom module + adapter example
cargo run # start engine
cargo run -- --config config.yaml # with config
cargo fmt && cargo clippy -- -D warnings # lint
make watch # watch modedocker build -t iii:local . # production (distroless)
docker build -f Dockerfile.debug -t iii:debug . # debug (Debian + shell)Docker image security: distroless runtime (no shell), non-root execution, Trivy scanning in CI, SBOM attestation, and build provenance.
See the Quickstart guide for step-by-step tutorials.

