[{"data":1,"prerenderedAt":493},["ShallowReactive",2],{"page-\u002Fblog\u002Fservicenow-business-rule-best-practices":3},{"id":4,"title":5,"author":6,"authorUrl":7,"body":8,"date":468,"dateUpdated":468,"description":469,"dqid":468,"excerpt":470,"extension":471,"faq":472,"headline":485,"meta":486,"navigation":487,"path":488,"seo":489,"socialImage":490,"stem":491,"tags":470,"__hash__":492},"content\u002Fblog\u002Fservicenow-business-rule-best-practices.md","ServiceNow Business Rule Best Practices: Avoid Recursion and Slow Transactions","SN-Tricks","https:\u002F\u002Fsn-tricks.com\u002Fabout",{"type":9,"value":10,"toc":457},"minimark",[11,15,18,23,26,29,33,41,78,81,88,92,95,98,112,141,145,152,155,241,248,252,255,258,261,350,354,361,364,368,375,381,384,388,391,421,424,428,453],[12,13,14],"p",{},"ServiceNow Business Rules make server-side automation feel simple: choose a table, define when the rule runs, and write a script. The trouble starts when a broadly scoped rule executes on every update, performs avoidable queries, or updates its own record again.",[12,16,17],{},"A reliable rule should do one job, run only when required, and add as little work as possible to the transaction. This guide explains how to design Business Rules that remain fast and understandable as an instance grows.",[19,20,22],"h2",{"id":21},"_1-confirm-that-a-business-rule-is-the-right-tool","1. Confirm That a Business Rule Is the Right Tool",[12,24,25],{},"Start with the requirement, not the script. ServiceNow recommends Flow Designer for most new process automation. A Business Rule is still appropriate when logic must run immediately before or after a database write, must execute in a particular order with other Business Rules, or simply needs to call a Script Include in that transaction.",[12,27,28],{},"Use a Business Rule for data enforcement and transaction-level logic. Use a flow for readable process orchestration, approvals, tasks, and reusable business automation. Do not implement the same requirement in both places; overlapping automation makes ordering and troubleshooting difficult.",[19,30,32],{"id":31},"_2-choose-the-correct-timing","2. Choose the Correct Timing",[12,34,35,36,40],{},"The ",[37,38,39],"strong",{},"When"," value determines both behavior and user impact:",[42,43,44,56,62,68],"ul",{},[45,46,47,50,51,55],"li",{},[37,48,49],{},"Before:"," Validate data, abort an invalid operation, or set fields on ",[52,53,54],"code",{},"current"," before the record is saved.",[45,57,58,61],{},[37,59,60],{},"After:"," Update related records or trigger work that must occur synchronously after the database operation.",[45,63,64,67],{},[37,65,66],{},"Async:"," Run work in a separate process after the database operation when the user does not need the result immediately.",[45,69,70,73,74,77],{},[37,71,72],{},"Display:"," Prepare server-side information, commonly through ",[52,75,76],{},"g_scratchpad",", before a form is shown.",[12,79,80],{},"Prefer a before rule when changing the current record. The platform saves those assignments as part of the original operation, so a second update is unnecessary. Reserve after rules for sequencing that genuinely must complete in the user's transaction. Move non-urgent, time-consuming work to async execution.",[12,82,83,84,87],{},"Remember that ",[52,85,86],{},"previous"," is unavailable in an async Business Rule. If async logic must know what changed, pass the required context through an event or persist the necessary state instead of assuming synchronous behavior.",[19,89,91],{"id":90},"_3-add-narrow-conditions-before-the-script-runs","3. Add Narrow Conditions Before the Script Runs",[12,93,94],{},"Every Business Rule should have a condition. A condition on the rule record prevents unnecessary script execution and makes Debug Business Rule output easier to interpret.",[12,96,97],{},"Be specific. Instead of running on every incident update and checking values deep inside the script, configure conditions such as:",[42,99,100,103,106,109],{},[45,101,102],{},"Active changes to false",[45,104,105],{},"Assignment group changes",[45,107,108],{},"Priority changes to 1 or 2",[45,110,111],{},"A required integration flag is true",[12,113,114,115,118,119,122,123,126,127,118,130,118,133,136,137,140],{},"Use ",[52,116,117],{},"changes()",", ",[52,120,121],{},"changesTo()",", or ",[52,124,125],{},"changesFrom()"," where field transitions matter. Also verify the ",[37,128,129],{},"Insert",[37,131,132],{},"Update",[37,134,135],{},"Delete",", and ",[37,138,139],{},"Query"," selections. A rule intended only for updates should not run on inserts by accident.",[19,142,144],{"id":143},"_4-never-call-currentupdate-in-a-business-rule","4. Never Call current.update() in a Business Rule",[12,146,147,148,151],{},"Calling ",[52,149,150],{},"current.update()"," starts another database operation. That operation can run Business Rules again, create duplicate notifications, and produce a recursive loop. ServiceNow explicitly advises against using it inside Business Rules.",[12,153,154],{},"For a before rule, assign the value directly:",[156,157,162],"pre",{"className":158,"code":159,"language":160,"meta":161,"style":161},"language-javascript shiki shiki-themes github-light github-light","(function executeRule(current, previous) {\n    if (current.priority.changesTo(1)) {\n        current.u_escalated = true;\n    }\n})(current, previous);\n","javascript","",[52,163,164,193,214,229,235],{"__ignoreMap":161},[165,166,169,173,177,181,183,186,188,190],"span",{"class":167,"line":168},"line",1,[165,170,172],{"class":171},"sKWpL","(",[165,174,176],{"class":175},"sCydW","function",[165,178,180],{"class":179},"se37E"," executeRule",[165,182,172],{"class":171},[165,184,54],{"class":185},"sj_tP",[165,187,118],{"class":171},[165,189,86],{"class":185},[165,191,192],{"class":171},") {\n",[165,194,196,199,202,205,207,211],{"class":167,"line":195},2,[165,197,198],{"class":175},"    if",[165,200,201],{"class":171}," (current.priority.",[165,203,204],{"class":179},"changesTo",[165,206,172],{"class":171},[165,208,210],{"class":209},"sMN4m","1",[165,212,213],{"class":171},")) {\n",[165,215,217,220,223,226],{"class":167,"line":216},3,[165,218,219],{"class":171},"        current.u_escalated ",[165,221,222],{"class":175},"=",[165,224,225],{"class":209}," true",[165,227,228],{"class":171},";\n",[165,230,232],{"class":167,"line":231},4,[165,233,234],{"class":171},"    }\n",[165,236,238],{"class":167,"line":237},5,[165,239,240],{"class":171},"})(current, previous);\n",[12,242,243,244,247],{},"Do not treat ",[52,245,246],{},"setWorkflow(false)"," as a routine workaround. It suppresses Business Rules and other workflow-related processing for that database action, which can bypass behavior another application expects. If an exceptional data-maintenance case truly requires it, isolate the code, document the side effects, and test notifications, auditing, and downstream automation.",[19,249,251],{"id":250},"_5-keep-rules-small-and-put-reusable-logic-in-script-includes","5. Keep Rules Small and Put Reusable Logic in Script Includes",[12,253,254],{},"A Business Rule should coordinate the trigger, not contain an entire application. Move reusable or complex logic into a Script Include and call a clearly named method from the rule.",[12,256,257],{},"This structure provides three benefits: the logic can be reused by flows, APIs, or scheduled jobs; the Business Rule remains easy to scan; and the Script Include can be tested separately. Keep the default function wrapper around advanced Business Rule code so local variables do not leak into the global server-side namespace.",[12,259,260],{},"Use an error prefix that operators can search:",[156,262,264],{"className":158,"code":263,"language":160,"meta":161,"style":161},"(function executeRule(current, previous) {\n    try {\n        new IncidentEscalationUtil().process(current);\n    } catch (error) {\n        gs.error('[IncidentEscalation] ' + error.message);\n    }\n})(current, previous);\n",[52,265,266,284,292,309,320,340,345],{"__ignoreMap":161},[165,267,268,270,272,274,276,278,280,282],{"class":167,"line":168},[165,269,172],{"class":171},[165,271,176],{"class":175},[165,273,180],{"class":179},[165,275,172],{"class":171},[165,277,54],{"class":185},[165,279,118],{"class":171},[165,281,86],{"class":185},[165,283,192],{"class":171},[165,285,286,289],{"class":167,"line":195},[165,287,288],{"class":175},"    try",[165,290,291],{"class":171}," {\n",[165,293,294,297,300,303,306],{"class":167,"line":216},[165,295,296],{"class":175},"        new",[165,298,299],{"class":179}," IncidentEscalationUtil",[165,301,302],{"class":171},"().",[165,304,305],{"class":179},"process",[165,307,308],{"class":171},"(current);\n",[165,310,311,314,317],{"class":167,"line":231},[165,312,313],{"class":171},"    } ",[165,315,316],{"class":175},"catch",[165,318,319],{"class":171}," (error) {\n",[165,321,322,325,328,330,334,337],{"class":167,"line":237},[165,323,324],{"class":171},"        gs.",[165,326,327],{"class":179},"error",[165,329,172],{"class":171},[165,331,333],{"class":332},"sOTlB","'[IncidentEscalation] '",[165,335,336],{"class":175}," +",[165,338,339],{"class":171}," error.message);\n",[165,341,343],{"class":167,"line":342},6,[165,344,234],{"class":171},[165,346,348],{"class":167,"line":347},7,[165,349,240],{"class":171},[19,351,353],{"id":352},"_6-control-queries-and-related-record-updates","6. Control Queries and Related-Record Updates",[12,355,356,357,360],{},"Database work inside a frequently triggered rule multiplies quickly. Query only when the rule's condition has already proven the work is necessary. Add explicit filters, use ",[52,358,359],{},"setLimit()"," when only one result is needed, and avoid querying inside loops.",[12,362,363],{},"For bulk related-record updates, ask whether the user must wait for completion. If not, use async processing, an event, or a scheduled mechanism. When synchronous processing is required, restrict the record set and avoid updating the same table that triggered the rule unless the design has been reviewed for recursion and ordering.",[19,365,367],{"id":366},"_7-debug-the-transaction-not-just-the-script","7. Debug the Transaction, Not Just the Script",[12,369,370,371,374],{},"Test with a reproducible record, user, expected result, and actual result. In a sub-production instance, ",[37,372,373],{},"System Diagnostics > Debug Business Rule"," shows which rules started, finished, or were skipped because their conditions failed.",[12,376,114,377,380],{},[52,378,379],{},"gs.debug()"," statements controlled by a system property for targeted diagnostics. This lets an administrator enable logging without editing production code. Disable debug properties after the investigation so routine transactions do not fill the system log.",[12,382,383],{},"Also review all rules on the table, including inherited rules. A script may be correct in isolation but fail because another rule changes the same field, runs in an unexpected order, or launches additional automation.",[19,385,387],{"id":386},"business-rule-review-checklist","Business Rule Review Checklist",[12,389,390],{},"Before promoting a rule, confirm that:",[392,393,394,397,400,403,409,412,415,418],"ol",{},[45,395,396],{},"A Business Rule is more suitable than Flow Designer or configuration.",[45,398,399],{},"The timing matches the requirement.",[45,401,402],{},"The rule has narrow conditions and correct operation checkboxes.",[45,404,405,406,408],{},"The script never calls ",[52,407,150],{},".",[45,410,411],{},"Reusable logic lives in a Script Include.",[45,413,414],{},"Queries are filtered, bounded, and outside loops.",[45,416,417],{},"Errors have a searchable prefix.",[45,419,420],{},"Insert, update, bulk update, and failure paths are tested in sub-production.",[12,422,423],{},"Good Business Rules are intentionally boring. They run at the right moment, touch only the required records, and leave enough diagnostic evidence for the next administrator to understand what happened.",[19,425,427],{"id":426},"official-servicenow-references","Official ServiceNow References",[42,429,430,439,446],{},[45,431,432],{},[433,434,438],"a",{"href":435,"rel":436},"https:\u002F\u002Fdeveloper.servicenow.com\u002Fprint_page.do?release=yokohama&category=now-platform&identifier=pro-dev-intro&module=guide",[437],"nofollow","Professional Developer Guide for the Now Platform",[45,440,441],{},[433,442,445],{"href":443,"rel":444},"https:\u002F\u002Fdeveloper.servicenow.com\u002Fdev.do?_escaped_fragment_=%2Fguides%2Fxanadu%2Fnow-platform%2Ftpb-guide%2Fbusiness_rules_technical_best_practices",[437],"Business Rules Technical Best Practices",[45,447,448],{},[433,449,452],{"href":450,"rel":451},"https:\u002F\u002Fdeveloper.servicenow.com\u002Fdev.do?_escaped_fragment_=%2Fguides%2Fwashingtondc%2Fnow-platform%2Ftpb-guide%2Fdebugging_best_practices",[437],"Debugging Best Practices",[454,455,456],"style",{},"html pre.shiki code .sKWpL, html code.shiki .sKWpL{--shiki-default:#24292E;--shiki-dark:#24292E}html pre.shiki code .sCydW, html code.shiki .sCydW{--shiki-default:#D73A49;--shiki-dark:#D73A49}html pre.shiki code .se37E, html code.shiki .se37E{--shiki-default:#6F42C1;--shiki-dark:#6F42C1}html pre.shiki code .sj_tP, html code.shiki .sj_tP{--shiki-default:#E36209;--shiki-dark:#E36209}html pre.shiki code .sMN4m, html code.shiki .sMN4m{--shiki-default:#005CC5;--shiki-dark:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sOTlB, html code.shiki .sOTlB{--shiki-default:#032F62;--shiki-dark:#032F62}",{"title":161,"searchDepth":195,"depth":195,"links":458},[459,460,461,462,463,464,465,466,467],{"id":21,"depth":195,"text":22},{"id":31,"depth":195,"text":32},{"id":90,"depth":195,"text":91},{"id":143,"depth":195,"text":144},{"id":250,"depth":195,"text":251},{"id":352,"depth":195,"text":353},{"id":366,"depth":195,"text":367},{"id":386,"depth":195,"text":387},{"id":426,"depth":195,"text":427},"2026-10-19","Build faster, safer ServiceNow Business Rules with the right timing, narrow conditions, reusable Script Includes, and practical debugging techniques.",null,"md",[473,476,479,482],{"question":474,"answer":475},"Should I use current.update() in a ServiceNow Business Rule?","No. ServiceNow advises against current.update() in Business Rules because it starts another database operation and can cause duplicate notifications or recursive loops. In a before rule, assign values directly to current; they are saved with the original operation.",{"question":477,"answer":478},"When should I use an async Business Rule?","Use an async Business Rule for work that can happen after the database operation and whose result is not needed immediately by the initiating user, such as slow related-record processing or an external call.",{"question":480,"answer":481},"What is the difference between before and after Business Rules?","A before rule runs before the database operation and is the normal place to validate or set fields on the current record. An after rule runs after the database operation and suits work on related records that must happen in sequence.",{"question":483,"answer":484},"How do I troubleshoot a slow ServiceNow Business Rule?","Reproduce the transaction in sub-production, enable Debug Business Rule, inspect which rules ran or were skipped, review transaction timing, and add property-controlled gs.debug statements around expensive queries or Script Include calls.","ServiceNow Business Rule Best Practices for Reliable Server-Side Logic",{},true,"\u002Fblog\u002Fservicenow-business-rule-best-practices",{"title":5,"description":469},"\u002Fsocial-card.png","blog\u002Fservicenow-business-rule-best-practices","ecgsUdZXo22Ihl4o1eGUAwtC9ekwIyOra5sYE9ERcvE",1792364640485]