v2.0

GoRules Version 2 is here - redesigned, now with managed cloud.GoRules Version 2 is here!

Watch the launch videoWatch

Switch from FICO Blaze Advisor to GoRules.

A step-by-step guide to moving your SRL rulesets, decision tables, ruleflows, and score models to GoRules: map the BOM to JSON, convert with the AI copilot, validate in parallel, and cut over.

What you get with GoRules

Where your rules land: the parts of GoRules most relevant to this migration.

Stateless Rust engine with per-node tracing

The Zen Engine evaluates a decision per request: JSON in, DAG traversal in topological order, JSON out. Each node runs exactly once, and the response can include a per-node trace with input, output, and sub-millisecond timing.

Rule changes are live in seconds

Rules are JSON decision graphs (application/vnd.gorules.decision). Edit in the editor, publish, and the change reaches production via an atomic releaseId swap - the decision cache expires within 5 seconds (DECISION_CACHE_TTL, configurable). No build step, no restart.

Managed cloud or self-hosted

Run on GoRules Cloud or self-host the same product as a single container image, including serverless via Lambda. One REST surface for evaluation: POST /projects/:projectId/evaluate/* with a JSON context.

Native SDKs across languages

The same Rust core ships as @gorules/zen-engine for Node.js, zen-engine for Python and Rust, zen-go for Go, io.gorules:zen-engine for JVM (Java and Kotlin), GoRules.ZenEngine for .NET, plus Swift, Android, and browser or Lambda via WASM.

The migration path

A step-by-step route from your current setup to running your rules on Zen Engine.

1. Identify rule services in decision-service mode

Blaze projects invoked via Server.createServer(<configPath>) and invokeService(serviceName, entryPointName, sessionInfo, argsArray) against an NdStatelessServer subclass are in scope for direct migration. Long-running monitoring services (event channel posting with is changed event rules) and interactive stateful sessions are not - GoRules evaluates per request, with no working memory and no event channel. Export the <RuleServerName>.server XML config from each deployment: each <DeployRulesServiceEntryPointConfig> element maps an EntryPointId to an SrlInvocationFunctional (SrlName and SrlArgumentType), and is the source of truth for the input/output shape each service exposes.

2. Map the BOM to a JSON context shape

Each Java BOM class becomes a nested JSON object; BOM properties become JSON fields (camelCase by convention). One-to-many relationships expressed as BOM arrays become JSON arrays. SRL static method calls (AutoPolicy.readAutoPolicy(<path>)) and class constants (NdProductInfo.PRODUCT_ADVISOR_TUTORIALS) move out of rules - either the caller pre-computes them or they become fields on the input. Method calls on BOM properties (decision.ReasonText.append("...")) become Zen expressions (flatten([reasons, ["new reason"]])) or JavaScript inside a functionNode. The SRL as a <Class> cast operator at the entry-point boundary is removed - the caller sends JSON directly, and an optional JSON Schema attached to the inputNode validates the shape if needed.

3. Translate SRL rulesets and decision tables

SRL if/then/else rules become decisionTableNode rows (conditions in input columns, actions in output columns) or switchNode branches with Zen boolean conditions. Decision table cell formats translate directly: >= {real 1} and < {real 2} becomes the half-open interval [100..300); >= {real} becomes >= 100; the Not Applicable wildcard becomes an empty cell. Ruleflow task sequences become DAG node chains. SRL splits (N branches with author-written SRL boolean conditions) become switchNode branches with Zen expressions. Patterns over collections (anyVehicle is any VehicleInfo in collection thePolicy.VehicleInfo) become a decisionNode with executionMode: "loop" and inputField: "policy.vehicles", or Zen map/filter/some/all on input arrays. The ignore(<pattern>) per-pattern dedup primitive is not needed - loop mode processes each array element independently. The sentinel-value catchall pattern (status = "pending" initial value, catchall fires only if status = "pending") maps cleanly to a wildcard row at the bottom of a decisionTableNode (empty cells in all input columns).

4. Handle score models and reason codes

Score models have no direct GoRules equivalent and require redesign as a graph composition. Author one decisionTableNode per characteristic (Country, Age, Years Licensed, etc.) with first hit policy, emitting one row per applicable bin and a partial_<name> field per characteristic. Add an expressionNode summing partial scores: { key: "score", value: "partial_age + partial_years_licensed + partial_country" }. Reason-code emission moves into a functionNode (JavaScript) that reads which bins matched and constructs a reasons array. Keeping bins mutually exclusive and collectively exhaustive is the author's responsibility in GoRules - there is no edit-time overlap validation. An All Other catch-all bin becomes a wildcard row in each per-characteristic table. Distance-based reason codes require manually computing per-characteristic baselines and ranking contributions inside the functionNode; rank-based reason codes are simpler - rank reasons by each characteristic's assigned reason-code priority or points lost, capped by a max count.

5. Validate against your Blaze baseline

Run representative inputs through the GoRules simulator. The response includes a per-node trace showing each node's id, name, input, output, and execution time. Compare results against the invokeService(...) output for the same inputs; the test data inside your generated Client.java (in the _<entryPoint>() private method) is a useful starting set of fixtures since it represents the input shape the deployment was already running against. Resolve any divergences before cutting over.

6. Swap the API integration

Replace the invocation chain - Server.createServer(<configPath>) returning a long-lived Server, invokeService(serviceName, entryPointName, sessionInfo, argsArray) for each call, server.shutdown() at the end, and the NdServerException/NdServiceException/NdServiceSessionException exception types - with a single REST call: POST /projects/:projectId/evaluate/<decisionKey> with body {"context": {...}, "trace": false} and the x-access-token header. The response is {performance, result, trace}. The generated Server.java, Client.java, and Runner.java files, the <RuleServerName>.server config (and its _ser.server variant), and the Build.bat/Run.bat scripts are retired once the cutover completes. Hosts that previously embedded NdStatelessServer directly can use the GoRules JVM SDK (io.gorules:zen-engine on Maven Central) to keep evaluation in-process.

GoRules AI

Let the copilot do the translation.

The AI copilot has no importer for BlazeAdvisor project artifacts - it does not parse .server XML config files, generated Server.java/Client.java files, Decision Table Templates, Score Model Templates, Reason Code Lists, or Rule Project archives. What it can do: accept pasted SRL rule text and generate decisionTableNode or expressionNode content; accept pasted decision-table cell values (or a CSV export from the Decision Table Editor) and generate decisionTableNode rows; accept the entry-point function signature and suggest a JSON context shape for the input; suggest Zen equivalents when SRL operators (is greater than, <>, possessive notation, for each <type> in <collection>) are described in text; help design the score-model decomposition (a decisionTableNode per characteristic, an expressionNode summing partial scores, a functionNode emitting reason codes) when characteristics, bins, and reason codes are described; convert ruleflow splits to switchNode when the N branch conditions are pasted. What it cannot do automatically: parse BOM class hierarchies - the developer must describe the input/output shape in text or JSON; migrate score models without explicit bin values, partial scores, and reason code lists provided by the developer; convert event-driven monitoring services or stateful sessions - these require redesign outside GoRules' request/response scope; handle is needed lazy event rules - the developer must decide which fields to precompute upstream in an expressionNode. Use the copilot iteratively: paste SRL rule bodies, describe what each ruleset computes, let it produce graph fragments, then refine.

Leave the build step
behind.

Bring your FICO Blaze Advisor rules over, run both engines in parallel, and cut over when the outputs match.