What is a Trigger?
A Trigger is what causes a Function to run. Triggers connect event sources to your functions, enabling automatic execution in response to:
HTTP requests
Scheduled cron jobs
Queue/pubsub messages
Stream events
Custom event sources
Triggers decouple your business logic (functions) from how they’re invoked. The same function can be triggered by HTTP, cron, or a queue without any code changes.
Trigger Architecture
Triggers have a two-level registration system:
Trigger Types : Define the kind of event source (e.g., http, cron, queue)
Triggers : Specific instances that connect a trigger type to a function
Built-in Trigger Types
HTTP Triggers
Map HTTP routes to functions. Powered by the RestApiModule.
iii . registerTrigger ({
type: 'http' ,
function_id: 'users.create' ,
config: {
api_path: 'users' ,
http_method: 'POST'
}
});
// With path parameters
iii . registerTrigger ({
type: 'http' ,
function_id: 'users.get' ,
config: {
api_path: 'users/:id' ,
http_method: 'GET'
}
});
HTTP triggers automatically parse request bodies, query parameters, and path params into the function input.
Cron Triggers
Schedule functions to run on a recurring basis using cron expressions.
iii . registerTrigger ({
type: 'cron' ,
function_id: 'reports.daily' ,
config: {
schedule: '0 9 * * *' // Every day at 9 AM
}
});
// Every 15 minutes
iii . registerTrigger ({
type: 'cron' ,
function_id: 'health.check' ,
config: {
schedule: '*/15 * * * *'
}
});
Queue Triggers
Subscribe functions to queue topics for async job processing.
iii . registerTrigger ({
type: 'queue' ,
function_id: 'orders.process' ,
config: {
topic: 'orders.created'
}
});
// Multiple subscribers to the same topic
iii . registerTrigger ({
type: 'queue' ,
function_id: 'notifications.send' ,
config: {
topic: 'orders.created'
}
});
Stream Triggers
React to real-time stream events over WebSocket channels.
iii . registerTrigger ({
type: 'stream' ,
function_id: 'analytics.track' ,
config: {
channel: 'user-events'
}
});
Registering Triggers
Basic Registration
import { init } from 'iii-sdk' ;
const iii = init ( 'ws://localhost:49134' );
// 1. Register the function
iii . registerFunction ({ id: 'greet' }, async ( input ) => {
return { message: `Hello, ${ input . name } !` };
});
// 2. Register the trigger
iii . registerTrigger ({
type: 'http' ,
function_id: 'greet' ,
config: {
api_path: 'greet' ,
http_method: 'POST'
}
});
// Now accessible at: POST http://localhost:3111/greet
Dynamic Triggers
Triggers can be registered and unregistered at runtime:
// Register a trigger
const triggerId = await iii . registerTrigger ({
id: 'my-http-trigger' , // Optional explicit ID
type: 'http' ,
function_id: 'users.list' ,
config: { api_path: 'users' , http_method: 'GET' }
});
// Later, unregister it
await iii . unregisterTrigger ( triggerId );
Custom Trigger Types
You can create custom trigger types by registering them from a worker:
// Register a custom trigger type
iii . registerTriggerType ({
id: 'slack' ,
description: 'Trigger functions from Slack events'
});
// Handle trigger registration
iii . on ( 'registerTrigger' , async ( trigger ) => {
if ( trigger . type === 'slack' ) {
const { event_type , channel } = trigger . config ;
// Set up Slack webhook listener
slackClient . on ( event_type , async ( event ) => {
if ( event . channel === channel ) {
// Fire the function
await iii . call ( trigger . function_id , event );
}
});
}
});
// Now others can use your trigger type
iii . registerTrigger ({
type: 'slack' ,
function_id: 'handle.message' ,
config: {
event_type: 'message' ,
channel: '#general'
}
});
Trigger Lifecycle
The trigger registration flow involves coordination between workers and the engine:
Protocol Messages
Under the hood, triggers use these WebSocket protocol messages:
RegisterTriggerType
Workers declare support for a trigger type:
{
"type" : "registertriggertype" ,
"id" : "http" ,
"description" : "HTTP API routes"
}
RegisterTrigger
Create a specific trigger instance:
{
"type" : "registertrigger" ,
"id" : "trigger-uuid" ,
"trigger_type" : "http" ,
"function_id" : "users.create" ,
"config" : {
"api_path" : "users" ,
"http_method" : "POST"
}
}
TriggerRegistrationResult
Engine confirms trigger registration:
{
"type" : "triggerregistrationresult" ,
"id" : "trigger-uuid" ,
"trigger_type" : "http" ,
"function_id" : "users.create" ,
"error" : null
}
UnregisterTrigger
Remove a trigger:
{
"type" : "unregistertrigger" ,
"id" : "trigger-uuid" ,
"trigger_type" : "http"
}
Internal Implementation
From the engine’s Rust implementation:
pub struct Trigger {
pub id : String ,
pub trigger_type : String ,
pub function_id : String ,
pub config : Value ,
pub worker_id : Option < Uuid >,
}
pub struct TriggerType {
pub id : String ,
pub _description : String ,
pub registrator : Box < dyn TriggerRegistrator >,
pub worker_id : Option < Uuid >,
}
pub trait TriggerRegistrator : Send + Sync {
fn register_trigger ( & self , trigger : Trigger )
-> Pin < Box < dyn Future < Output = Result <(), Error >> + Send >>;
fn unregister_trigger ( & self , trigger : Trigger )
-> Pin < Box < dyn Future < Output = Result <(), Error >> + Send >>;
}
The TriggerRegistry maintains all registered trigger types and trigger instances. When a worker disconnects, all its triggers are automatically unregistered.
Firing Triggers Manually
You can manually fire all triggers of a specific type from the engine:
// From within a module or engine code
engine . fire_triggers ( "user.created" , json! ({
"user_id" : "123" ,
"email" : "[email protected] "
})) . await ;
This invokes all functions registered to triggers of that type.
Best Practices
Use specific trigger IDs Provide explicit IDs for triggers you’ll need to unregister later
Handle registration errors Check TriggerRegistrationResult for errors and retry if needed
Clean up on disconnect The engine auto-cleans triggers when workers disconnect, but unregister explicitly when possible
Keep configs simple Trigger configs should be JSON-serializable and well-documented
Next Steps
Functions Learn about the functions that triggers invoke
Architecture Understand the engine and worker model