SfSkills Domains Docs GitHub

Home / omnistudio / business-rules-engine

business-rules-engine

Use when designing, building, or troubleshooting OmniStudio Business Rules Engine (BRE) artifacts: Decision Tables, Decision Matrices (rule matrices), and Expression Sets used for eligibility determination, pricing, discounting, or any complex multi-attribute rule evaluation.

Open the skill folder on GitHub


Business Rules Engine

Use this skill when designing or troubleshooting OmniStudio Business Rules Engine (BRE) artifacts — Decision Tables, Decision Matrices, and Expression Sets — for eligibility determination, product qualification, pricing, or any multi-attribute conditional logic that must be managed by business analysts without deployments. This skill is distinct from Calculation Procedures, which perform sequential math; BRE is for rule-based lookup and eligibility evaluation.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

Decision Tables

A Decision Table is a rule-based lookup artifact. It consists of a set of condition columns (input attributes) and output columns (outcomes). Each row defines one rule: when all condition columns for that row match the provided inputs, the output columns for that row are returned.

Decision Tables use an operator per condition column (Equals, Not Equals, In, Not In, Range, etc.). Rows are evaluated in priority order; the first matching row wins. If no rows match, the table returns null or a default output row if one is configured.

The underlying metadata type is DecisionTable, with rows stored as DecisionTableRow and column definitions in DecisionTableColumn. Decision Tables are versioned — each version is independent, and only one version can be active at a time. The platform metadata file extension is .decisionTable-meta.xml.

Decision Tables are best suited for discrete lookup scenarios: product eligibility matrices, discount tier lookups, geographic rate tables, and similar flat rule sets. They are not suited for complex nested boolean logic — use Expression Sets for that.

Expression Sets

An Expression Set (ExpressionSet metadata type) defines a tree of condition groups and conditions evaluated with AND/OR operators. The result is a boolean or a computed output value depending on configuration. Expression Sets are used for eligibility scoring, approval threshold checks, and discount qualification where the logic is a combination of conditions rather than a simple row lookup.

Expression Sets support nested condition groups (a group can contain sub-groups), making it possible to express (A AND B) OR (C AND NOT D) logic that cannot be captured in a flat decision table. An Expression Set version (ExpressionSetVersion) must be activated before it can be called. Expression Sets can call Decision Tables internally as lookup sources.

The API invocation surface for Expression Sets is ExpressionSetService.evaluate(expressionSetApiName, inputMap) in Apex, or the REST endpoint POST /connect/business-rules/expression-sets/{expressionSetApiName}/actions/evaluate.

Versioning and Activation

All BRE artifacts (Decision Tables and Expression Sets) use a versioning model:

Metadata deployment promotes the version definition but does not activate it automatically. Post-deployment activation must be performed via the BRE UI or via the Connect API PATCH endpoint.

Runtime Execution

BRE rules are synchronous and execute within the current transaction context. Two primary invocation paths exist:

  1. Integration Procedure (IP) callout action — Add an Action element of type BusinessRules or DecisionTable in the IP step palette. Pass input attributes as the action's input JSON. Map output JSON back to IP variables. This is the most common pattern for OmniScript-driven journeys.
  2. Apex invocation — Use BusinessRules.ExpressionSetService.evaluate(String expressionSetName, Map<String, Object> inputs) for programmatic calls. The return type is Map<String, Object> containing the output attribute values. This path is used in trigger-based eligibility checks or batch reprocessing.

Regardless of invocation path, input attribute names are case-sensitive and must exactly match the column or condition attribute API names defined in the BRE artifact.


Common Patterns

Pattern 1: Product Eligibility Decision Table

When to use: When a product or service is available only when a set of conditions are simultaneously true — for example, a broadband product that requires a service area code, a credit tier, and an account type match.

How it works:

  1. Define the Decision Table with one condition column per eligibility attribute (ServiceArea, CreditTier, AccountType) and one output column (IsEligible = true/false, or EligibleProductCode).
  2. Add a row for each valid combination. Use In operator for multi-value columns instead of repeating rows.
  3. Add a default row (all conditions blank) returning IsEligible = false to handle unmatched inputs without returning null.
  4. Create version 1, populate rows, and activate the version.
  5. In the Integration Procedure that drives the OmniScript journey, add a BusinessRules action element. Pass context attributes as inputs. Map the output IsEligible to an IP variable.
  6. In the OmniScript, add a Condition Step reading the IP variable to branch the journey.

Why not a Flow Decision element: A Flow Decision requires a developer deployment for every rule change. A Decision Table lets a business analyst update rows via the BRE UI with no deployment.

Pattern 2: Complex Eligibility with Expression Set Condition Groups

When to use: When eligibility depends on nested boolean logic — for example, an insurance quote is eligible if (age >= 18 AND state IN ['CA','TX']) OR (age >= 21 AND hasExistingPolicy = true).

How it works:

  1. Create an Expression Set definition for QuoteEligibility.
  2. In version 1, create two condition groups at the top level joined by OR.
  3. Group 1: add conditions age >= 18 AND state IN ['CA','TX'].
  4. Group 2: add conditions age >= 21 AND hasExistingPolicy = true.
  5. Set the Expression Set output to return a boolean result or an eligibility score.
  6. Activate the version.
  7. Call from Apex: BusinessRules.ExpressionSetService.evaluate('QuoteEligibility', new Map<String, Object>{'age' => 25, 'state' => 'CA', 'hasExistingPolicy' => false}).
  8. Inspect the return map for the output attribute key.

Why not a decision table: A flat decision table cannot represent (A AND B) OR (C AND D) without exploding into a combinatorial row set. Expression Sets handle nested boolean logic cleanly.

Pattern 3: Versioned Rule Rollout with Parallel Draft

When to use: When the business wants to author next-quarter rules while current rules remain live in production.

How it works:

  1. Keep the current version active in production.
  2. Create version 2 in Draft status. Authors can edit draft rows without affecting runtime.
  3. Test version 2 using the BRE Test tab (provide sample inputs and verify expected outputs).
  4. Deploy version 2 metadata to production (metadata deploy does not activate).
  5. On the go-live date, activate version 2 via the BRE UI or via a Connect API PATCH call. The platform deactivates version 1 automatically.
  6. Keep version 1 in Inactive status for rollback reference.

Why not deploy-and-activate in one step: Separating deploy from activation allows business sign-off in production data before go-live, reducing risk.


Decision Guidance

SituationRecommended ApproachReason
Flat rule lookup with discrete input combinationsDecision TableRow-based evaluation is fast, auditable, and business-analyst-editable
Nested AND/OR eligibility logicExpression Set with condition groupsSupports arbitrary boolean trees; Decision Tables cannot represent nested logic
Rules change frequently without IT involvementBRE Decision Table or Expression SetBusiness analysts manage rules in UI with no deployment required
Need to call rules from Apex trigger or batch jobApex ExpressionSetService.evaluate()Direct synchronous Apex call; no HTTP overhead
Need to call rules from OmniScript journeyIntegration Procedure with BusinessRules actionIP manages input/output mapping and context variable passing
Future-effective rule version neededDraft version + manual activation on go-live dateBRE does not support date-effective activation; activation is manual
Rule has > 500 rowsCheck the published row/column ceilings first, then split by a primary keyStandard decision tables have published default ceilings — 100,000 processable rows, 15 columns, 30 input conditions (Salesforce can extend all three); advanced tables process up to 20,000,000 rows. Partition for auditability, not because no limit exists (see references/well-architected.md)
Rule returns wrong value after activationCheck input attribute name case sensitivity and verify only one version is ActiveMost runtime mismatches are attribute name case or stale version activation

Step-by-step instructions for an AI agent or practitioner working on BRE design:

  1. Gather requirements — Document input attributes (names, data types, valid values), expected outputs, operator requirements (range vs. equals vs. set membership), and frequency of rule changes. Confirm Industries license and org API version.
  2. Choose artifact type — Use the Decision Guidance table to select Decision Table, Expression Set, or a combination. Document the choice and reasoning.
  3. Design the schema — Define column names (these become the input attribute API names used at runtime), data types, operators, and output column names. Use snake_case or camelCase consistently — names are case-sensitive at runtime.
  4. Build and populate — Create the artifact in the BRE designer or via metadata deploy. Add all rows/conditions. Add a default/fallback row for unmatched inputs if appropriate.
  5. Test in BRE UI — Use the built-in Test tab to run sample inputs including boundary cases and confirm expected outputs before activating.
  6. Activate — Activate the version via the BRE UI or Connect API. Verify only one version is Active. Do not activate in production without prior testing in a lower environment.
  7. Integrate and validate end-to-end — Wire the BRE artifact into the Integration Procedure or Apex caller. Run end-to-end tests through the consuming OmniScript or process. Confirm attribute name alignment and output mapping.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. Attribute name case sensitivity causes silent null returns — Decision Table column API names and Expression Set condition attribute names are case-sensitive. If the IP or Apex caller passes creditTier but the column is defined as CreditTier, the lookup receives null for that input and may match the wrong row or return no result. There is no runtime error — the mismatch is silent.
  2. Activating a new version in UI does not deploy it to other orgs — BRE activations made through the UI are data-layer changes (record updates), not metadata changes. A metadata retrieve/deploy cycle captures version content but not the activation flag. Teams that rely solely on metadata deployment will find that versions arrive in production as Draft and must be activated post-deploy. Build a post-deployment activation step into the release process.
  3. No date-effective version selection in BRE Decision Tables — Unlike Calculation Matrices, Decision Tables and Expression Sets do not support date-effective version ranges. There is one active version at any given time. If future-effective rules are required, you must manually activate on the go-live date or build a wrapper Integration Procedure that routes to different rule artifacts by date.
  4. Decision Table row evaluation stops at first match — Rows are evaluated in priority order and execution stops when a match is found. If two rows could both match a given input (overlapping condition ranges or values), only the higher-priority row is returned. Overlapping rows that should have different outcomes is a common authoring error that is not flagged in the UI.
  5. Expression Set outputs are untyped Object in Apex return map — ExpressionSetService.evaluate() returns Map<String, Object>. All output values are Object type and require explicit casting. Casting a numeric output to String or a boolean output to Decimal will throw a TypeException at runtime. Always cast defensively using instanceof or a try/catch.

Output Artifacts

ArtifactDescription
Decision Table column definitionInput column names, data types, operators, and output column names — the schema used by both the BRE designer and the runtime caller
Expression Set structureCondition groups, operator tree (AND/OR nesting), condition attribute names, and output definition
Versioning planWhich version is active, what is in draft, effective date for planned activation, and rollback procedure
Integration Procedure wiring notesAction element type, input attribute mapping, output variable mapping, and error handling strategy
BRE test case setSample inputs covering happy path, boundary values, and unmatched inputs with expected outputs

Package files