Advanced Features
A/B split
Route a percentage of instances to variant A and the remainder to variant B via deterministic hash-based selection. Ideal for subject line testing, send-time experiments, and content variants.
{
"type": "ab_split",
"id": "subject_line_test",
"split_key": "{{context.data.email}}",
"variants": [
{
"weight": 50,
"block": {
"type": "step", "id": "variant_a",
"handler": "send_email",
"params": { "subject": "Don't miss this deal" }
}
},
{
"weight": 50,
"block": {
"type": "step", "id": "variant_b",
"handler": "send_email",
"params": { "subject": "Your exclusive offer expires soon" }
}
}
]
}The split_key is hashed deterministically — the same contact always gets the same variant, enabling reliable attribution and consistent user experience.
Circuit breaker
Per-handler circuit breaker protects downstream services from being overwhelmed by a cascade of failures. Configured per handler name.
ClosedNormal operation — tasks dispatched to the handlerOpenHandler tripped — tasks fail immediately without dispatching (configurable cooldown period)HalfOpenCooldown expired — one probe task dispatched; success closes, failure re-opens
# Inspect circuit breakers
GET /circuit-breakers
# Reset a tripped breaker
POST /circuit-breakers/{handler_name}/resetSLA timers and deadlines
Attach a wall-clock deadline to any step. If the step has not completed by the deadline, an escalation handler fires automatically.
{
"type": "step",
"id": "resolve_ticket",
"handler": "wait_for_resolution",
"deadline": "4h",
"on_deadline_breach": {
"handler": "escalate_to_manager",
"params": {
"ticket_id": "{{context.data.ticket_id}}",
"message": "SLA breach: ticket unresolved after 4 hours"
}
}
}Workflow interceptors
Attach lifecycle hooks to a sequence definition. Interceptors fire at configurable points without modifying the sequence logic.
// Part of the sequence definition
"interceptors": [
{
"on": "before_step",
"handler": "audit_logger",
"params": { "namespace": "{{context.config.namespace}}" }
},
{
"on": "on_failure",
"handler": "notify_oncall",
"params": { "channel": "pagerduty" }
},
{
"on": "on_complete",
"handler": "update_crm",
"params": { "status": "sequence_done" }
}
]Valid on values: before_step, after_step, on_signal, on_complete, on_failure.
Encryption at rest
Encrypt instance metadata and context at the field level using AES-256-GCM. Configure a 32-byte hex key and all new instances are stored encrypted.
# Environment variable
ORCH8_ENCRYPTION_KEY=your-32-byte-hex-key-here
# Or in orch8.toml
[security]
encryption_key = "your-32-byte-hex-key-here"Encryption is transparent to handlers — decryption happens before the handler receives the context.
Audit log
Every state transition is recorded in an append-only audit_log table. Query the full history for any instance via the REST API.
GET /instances/{id}/audit
// Response
[
{ "event": "instance_created", "at": "2024-01-15T10:00:00Z" },
{ "event": "step_started", "block_id": "send_email", "at": "2024-01-15T10:00:01Z" },
{ "event": "step_completed", "block_id": "send_email", "at": "2024-01-15T10:00:02Z" },
{ "event": "instance_waiting", "reason": "delay_3d", "at": "2024-01-15T10:00:02Z" }
]Debug mode
Set breakpoints on step IDs in instance metadata. The engine pauses execution at each breakpoint, allowing step-through inspection via REST or CLI. Resume with a Resume signal.
// Enable breakpoints at creation
{
"metadata": {
"_debug_breakpoints": ["send_email", "check_reply"]
}
}// Inspect state
GET /instances/{id}
// Step forward
POST /instances/{id}/signals
{ "signal_type": "resume" }