Rule Rhai
Rhai for rules — Rule Rhai — is Conduit’s scripted policy on matching rules: logic you cannot express with built-in actions alone. You keep .rhai files beside your config, reference them from rules via type: rhai, and Conduit runs them at Request rules and Response rules on the dataplane.
Rhai for rules acts on a policy txn object; it does not edit DNS wire bytes. For how rules and scripts fit together at the policy layer, see Policy & routing and Rules and actions.
When to use Rhai for rules
Built-in selectors and actions cover most routing — pool choice, tags, egress overrides, drop, and retry. Reach for Rhai for rules when you need logic on top of that, for example:
- Branch on a lookup table (
lookup) on the request hook — for example map qname to a pool before Route, instead of a long static rule list - Combine several checks in one script — for example upstream rcode and a tag set on the request hook →
set_retry_pool("backup")andrequest_retry()on the response hook - Branch on backend health with
runtime.routing()— pool failover when eligible count drops, retry when the attempt backend is applied down, or inspect latency EWMA /weight_factorfor canary logging - Set tags that drive event export filters or tracing activation
- Apply deterministic per-transaction sampling in scripts —
txn.sample_percent,sample_percent_for_qname,sample_percent_for_rule, or cadence gatesevery_nth_worker/every_nth_global(YAML parity table on Transaction API — Sampling) - Publish custom counters (
conduit_user_*) viametrics.inc— User metrics
If declarative YAML is enough, prefer Rules and actions. Rhai for rules adds flexibility and operational surface (script files, sandbox limits, compile-time checks on reload), but runs an interpreted script on the query path for each matching rule — higher per-query cost than built-in actions alone. Prefer built-in selectors and actions when they express the same policy.
How scripts attach to rules
Rhai does not run on every query by default. A script runs only when a matching rule on that hook includes a rhai action whose value is the script path.
On each hook, Conduit still uses match_mode: first_match: it walks rules top to bottom and stops at the first rule whose selectors all match. On that rule, every action — built-in and type: rhai — runs in list order at the position where it appears.
The script receives a sandboxed txn object for the current transaction. It can refine what earlier actions already set — for example override pool choice or add tags — or drop / request retry on its own.
sequenceDiagram
participant Hook as Request or response hook
participant Rule as First matching rule
participant Step as Next action in list
Hook->>Rule: Selectors match?
loop Each action in list
Rule->>Step: built-in or rhai
Step-->>Rule: txn effects
end
Rule-->>Hook: resolve drop / retry / continue
Hook timing, first-match rules, and YAML wiring: Rules and actions. Phase guards and pairing request/response scripts: Hooks and phases. Host API map: Host API overview. txn methods: Transaction API (txn).
Minimal example
Config — route names ending in .vip.example. through a script (paths resolve relative to the config file directory; see Config file — path resolution):
schema_version: 1
listeners:
listeners:
- address: "127.0.0.1:15353"
protocol: udp
pools:
- name: default
backends:
- address: "127.0.0.1:5300"
- name: vip
backends:
- address: "127.0.0.1:5301"
rhai:
max_operations: 10000
max_call_depth: 32
hook_timeout_ms: 50
rules:
match_mode: first_match
rules:
- name: vip-routing
hook: request
selectors:
- type: qname_suffix
value: ".vip.example."
actions:
- type: rhai
value: scripts/set-vip-pool.rhai
Script (scripts/set-vip-pool.rhai):
txn.set_tag("tier", "vip");
txn.set_pool("vip");
After SIGHUP, conduitctl reload, or conduitctl apply, Conduit compiles the script into the active runtime snapshot. Queries that match the rule run the script on the request hook before Route.
Configuration
| Concern | Where | Topic page |
|---|---|---|
| Sandbox limits (operations, call depth, hook timeout) | rhai: |
Sandbox limits |
| Script path on a rule | rules: → type: rhai |
Rules and actions, Reference: rules |
| Lookup tables for scripts | data_sources: |
Data sources, Lookups |
| Custom metric names and labels | Declared in script source at compile time | User metrics |
When you omit the top-level rhai: block, Conduit still applies default sandbox limits (10000 operations, call depth 32, 50 ms hook timeout). You only need rhai: in the file when you want to tune those limits.
Omitting rules: entirely means no scripts run — Rhai is opt-in per rule.
When script changes take effect
Conduit reads and compiles .rhai files when it builds a runtime snapshot — at process start and on each successful reload or apply. Editing a script on disk has no effect on live queries until that snapshot swap succeeds.
conduitctl validateruns the same YAML checks and snapshot compile as startup/reload — use it to catch missing script paths or Rhai syntax errors before deploy.- Transactions already in flight keep the scripts they started with.
- If reload validation fails (bad script syntax, missing file, invalid metric registration), Conduit keeps the previous working snapshot and DNS keeps flowing. See Configuration model.
Script errors and limits
Each hook invocation runs under sandbox limits (max_operations, max_call_depth, hook_timeout_ms). If a script traps, exceeds a limit, or calls an API not allowed on that hook (for example response() on the request hook), Conduit logs a warning and continues without applying further script effects for that hook — the query is not dropped solely because the script failed.
Built-in actions on the same rule still ran before the script. Use Logging at warn or higher to see rhai script error lines; built-in forward health and query counters still reflect the rest of the pipeline.
Read in order
- Host API overview — five scope objects
- Hooks and phases — request vs response from a script author’s view, phase guards, pairing scripts
- Transaction API (
txn) — per-query policy methods and YAML equivalents - Runtime API —
runtime.routing()health reads - Sandbox limits —
rhai:fields, defaults, tuning and failure behavior - Lookups —
lookup()/lookup_ip()(Data sources fordata_sources:config) - User metrics —
metrics.inc,conduit_user_*export
Prerequisites
- Architecture and packet path — pipeline phases and where Request rules / Response rules run
- Rules and actions — selectors, built-in actions, and
rhaiaction wiring - Config file — path resolution for script and CSV paths
Related
- Rhai overview — Rhai for rules
- Policy & routing — pools, retries, and declarative policy
- Dual-stack forwarding —
set_source_v4/set_source_v6in rules and Rhai - Event export — tag-based sink filters
- Built-in metrics — dataplane counters alongside user metrics