メインコンテンツへスキップ
見出し画像

ServiceNowのBusiness Ruleはいつ動く? before/after/asyncの違いを実機の件数で確認


    保存したらフォームの値が勝手に書き換わった、あるいは保存自体が止まった経験はないでしょうか。多くの場合、原因はサーバー側で動くBusiness Ruleです。ServiceNowはこの処理をsys_scriptという1つのテーブルにまとめています。いつ動くか(when)・同じタイミングの中の順番(order)・動く条件(condition)を、1レコードのフィールドから読み取れます。Zurich PDIでBusiness Rule 5,719件を数え、構造を実機で確認しました。

    検証環境:Zurich PDI / OOTB / 2026-08-08 確認


    結論:Business Ruleは1レコードのフィールドで読み解ける

    全体像を先に示します。

    • Business Ruleはsys_scriptという1つのテーブルに、1ルール=1レコードで保存されます。Client ScriptやUI Actionと同じsys_metadata(Application File)配下の「アプリ構成」として管理される仕組みで、業務データのテーブルではありません。

    • 実行タイミングはwhenが決めます。before/after/asyncはDB保存に、displayはフォーム表示に絡み、全5,719件のうち約6割がbeforeでした。

    • 同じwhen内の順番はorder、実際に動くかどうかはaction_*(反応するDB操作)→filter_condition→condition(Advancedタブ)の3段階で絞られます。

    • 処理本体はadvancedフラグで2通りに分かれ、今回のPDIではほぼ全件(5,650件)がscriptを直接書くAdvancedモードでした。

    incidentのBusiness Ruleを1件開くと、この構造が1フォームに集約されているのが分かります。


    画像

    when(実行タイミング)を軸に、DB操作の前後でBusiness Ruleがどこに位置するかを整理すると、次の流れになります。


    画像

    図の色は6種類の意味に固定しています。濃紺はデータベース書き込みという起点です。橙は件数が突出しているタイミング(before)、緑は保存後に同期で進む処理(after)を表します。紫は別トランザクションで動く処理(async)、水色はクライアントへの参照渡し(display)です。灰色は経路上の中継点を示します。before・display・DB書き込みが並ぶ縦の流れが本線で、DB書き込みの後にafterとasyncへ分岐します。


    Business Rule(ビジネスルール)とは

    Business Ruleとは、レコードが表示・挿入・更新・削除されたとき、またはテーブルが照会(query)されたときに、サーバー側で動くJavaScriptの処理です。「保存したらStateを変える」「条件を満たしたら通知を投げる」「ユーザーが見られるレコードを絞る」といった、データの整合性や自動化を担う中心的な仕組みです。

    ServiceNowでは、このBusiness Ruleを格納する中心テーブルがsys_scriptです。画面ではSystem Definition > Business Rulesから一覧でき、各レコードが1つのルールに対応します。**「いつ(when)」「どの操作で(action_*)」「どんな条件で(condition)」「何を(script)」**するかを、1レコードの中のフィールドで定義します。


    sys_scriptはどこに位置するテーブルか

    最初に押さえたいのは、sys_scriptがincidentやcmdb_ciのような「業務データのテーブル」ではない、という点です。


    画像

    今回のPDI(Zurich / OOTB)で確認すると、sys_scriptはsys_metadata(Application File)を継承するテーブルでした。sys_metadataはUpdate Setで持ち運べる「アプリ構成」の基底です。つまりBusiness Ruleは「設定・構成」側のレコードとして管理されます。Client Script(sys_script_client)やUI Action(sys_ui_action)も、同じsys_metadata配下の兄弟という位置づけです。いずれも「どのテーブルに対する処理か」という情報を持つ点は共通しています。

    Business Ruleが「どの業務テーブルに効くか」は、sys_scriptの中のcollection(画面ラベル: Table)フィールドで決まります。incidentのBusiness Ruleならcollection=incident、という具合です。sys_script自体は1つのテーブルですが、collectionを通じてあらゆる業務テーブルに処理を差し込めます。接点は1つのフィールドです。

    テーブル定義は、次のURLで確認できます(先頭の<YourInstance>は自分のインスタンスに置き換えてください)。

    https://<YourInstance>/sys_db_object_list.do?sysparm_query=name=sys_script


    画像

    Business Ruleはいつ動く? whenは4種類

    Business Ruleで最初に決めるのがwhen(実行タイミング)です。同じ「保存時の処理」でも、DBに書き込む前なのか後なのか、同期か非同期かで意味がまったく変わります。

    • before … DBに保存する直前に動きます。currentの値を補正したり、current.setAbortAction(true)で保存自体を中断できます。入力値のチェックや自動補完に向きます。

    • after … DBに保存した直後に、同期で動きます。保存済みのレコードを前提に、関連レコードを更新するなどの後処理に向きます。

    • async … 保存後に非同期(バックグラウンド)で動きます。スケジュールキューに積まれて後追い実行されるため、ユーザーには素早く制御が戻りますが、反映までに時間差が出ます。重い後処理に向きます。

    • display … フォームを表示する前に動き、g_scratchpadを使ってサーバー側の情報をクライアント(ブラウザ)へ受け渡します。Client Scriptから使う値を準備する用途です。

    before/after/asyncが「DB操作(保存)」に絡むのに対し、displayだけは「フォーム表示」に絡みます。同じwhenフィールドでも、トリガーになるイベントが違う点に注意が必要です。

    実機でwhen別の件数を数えると、傾向がはっきり出ます。


    画像

    beforeが3,441件と最多で、全体(5,719件)の約6割を占めていました。afterが1,456件、displayが601件、asyncが148件です。保存前に値を整える処理が、もっとも多く使われていることが件数からも読み取れます。なお内部値としては、旧仕様のasync(非推奨)が別に64件残存していましたが、現在の有効な選択肢はbefore/after/async/displayの4種です。

    whenの選択肢は、次のURLで一覧できます。

    https://<YourInstance>/sys_choice_list.do?sysparm_query=name=sys_script^element=when^inactive=false^ORDERBYsequence


    画像

    公式のBusiness rules(Zurich)に、Business Ruleが「表示・挿入・更新・削除・照会のときに動くサーバー側スクリプト」であることと、各タイミングの考え方が説明されています。


    同じwhen内の順番はどう決まる? order

    whenが同じBusiness Ruleが複数あるとき、どちらが先に動くかを決めるのがorder(実行順)です。orderの数値が小さいほど先に実行され、同じwhen・同じテーブルの中で順番に処理されます。

    今回のPDIでは、orderを持たない(空の)BRは0件で、全件がorderを持っていました。値の分布を見ると、既定値の100が4,840件(全体の84.6%)と圧倒的です。ほかはorder未満の値が265件(うちorder=0が15件)、100超が614件でした。多くのBusiness Ruleはorder=100のままにし、特定の前後関係が必要なものだけ値をずらす、という使われ方が読み取れます。

    複数のBusiness Ruleが同じwhenで動くとき、実行順の食い違いはバグの原因になりやすいところです。「値を補正するbefore BR」と「補正後の値を前提にチェックするbefore BR」があるなら、補正側のorderを小さくして先に動かす、といった設計になります。順番は偶然ではなく設計で決めるものです。


    動く条件はどこで絞られる? filter_conditionとcondition

    Business Ruleは、いつでもscriptを実行するわけではありません。「この操作・この条件のときだけ動く」というフィルタが、複数段で効きます。


    画像

    sys_scriptのフィールドを見ると、条件は大きく次の段階で評価されます。

    1. action_insert / action_update / action_delete / action_query … そのBRが反応するDB操作。複数をONにでき、insertとupdateの両方に反応、といった指定が可能です。実機ではaction_update=trueが3,825件、action_insert=trueが3,670件でした。action_delete=trueが961件、action_query=trueが84件です(フラグは独立なので合計は総数と一致しません)。

    2. filter_condition(画面: When to RunのFilter Conditions) … 「stateが3に変わったら」のような宣言的な条件。コードを書かずにUIで組み立てます。設定しているBRは1,856件(32.5%)でした。

    3. condition(画面: AdvancedタブのCondition) … advanced=trueのときに使う、JavaScriptの追加条件。filter_conditionを満たした上で、さらにこの式がtrueのときだけscriptが動きます。設定しているBRは1,550件(27.1%)でした。

    filter_conditionが先に評価され、それを満たした場合にのみcondition(JavaScript)が評価される、という二段構えです。無条件(フラグのみ)で動くBusiness Ruleの方がまだ多いものの、3割前後は宣言的フィルタや追加条件で対象を絞り込んでいました。重いJavaScript条件をいきなり全レコードで走らせず、まず宣言的フィルタで絞る設計になっています。無駄打ちを減らす工夫です。


    scriptは書く?書かない? advancedで分かれる処理本体

    Business Ruleには、処理の書き方が2通りあります。それを切り替えるのがadvanced(高度モード)フラグです。


    画像
    • advanced=false … scriptを書きません。template(Set field values)で「このフィールドにこの値を入れる」といった単純な値セットや、メッセージ表示だけを宣言的に行います。

    • advanced=true … script(サーバー側JavaScript)を直接書くモード。Advancedタブが現れ、conditionとscriptを編集できます。current / previous / g_scratchpadなどのオブジェクトを使った自由な処理が書けます。

    今回のPDIでは、advanced=trueが5,650件、advanced=falseが69件でした。OOTBのBusiness Ruleは、ほぼすべてがscriptを直接書く高度モードで、宣言的な値セットだけのBRはごく少数です。実務でも、少し凝った処理になればすぐadvancedをONにするため、この偏りは自然な結果に見えます。テンプレートより書く方が速いからです。

    beforeタイミングのBRでは、abort_action(操作中断)も使えます。実機ではabort_action=trueが157件あり、保存をブロックして整合性を守る用途で使われています。

    主な固有フィールドを役割で整理すると次のとおりです。ラベルは画面上の表示名で、実機どおり記載します。


    画像

    どのテーブルに効く? collectionと継承の関係

    Business Ruleが「どのテーブルに効くか」はcollection(Table)で決まります。incidentに紐づくBR、cmdb_ciに紐づくBRというように、対象テーブルごとにsys_scriptのレコードが束ねられます。

    今回のPDIでは、collection=incidentのBusiness Ruleは39件(active 38件)でした。collection=taskのBRは37件(active 35件)です。テーブルを指定しない(collectionが空の)BRも5件あり、これらは特定テーブルに限らず動く扱いです。


    画像

    ここで注意したいのは、incidentはtaskを継承するテーブルだという点です。incidentのレコードを保存すると、incidentに紐づくBRだけでなく、親のtaskに紐づくBRも対象になり得ます。継承時の実行マージ順の実測は検証範囲外ですが、「incidentの挙動」を調べるときは、incidentだけでなくtaskのBusiness Ruleも合わせて見る必要があります。片方だけでは足りません。

    特定テーブルのBusiness Ruleは、次のURLで確認できます。

    https://<YourInstance>/sys_script_list.do?sysparm_query=collection=incident^active=true^ORDERBYwhen^ORDERBYorder


    画像

    全フィールドは、次のURLで一覧できます。

    https://<YourInstance>/sys_dictionary_list.do?sysparm_query=name=sys_script^elementISNOTEMPTY


    画像

    実機で気づいたこと

    この記事を最初に書いたときのsys_scriptの総数は5,500件でした。約7週間後に同じPDIで数え直すと5,719件に増えていました。カスタマイズは何も加えていません。219件、4%の増加です。パッチや自動アップグレードで標準のBusiness Rule自体が増減することが分かります。OOTBの件数は確認した時点のスナップショットであり、固定値だとは考えない方が安全です。件数は生き物です。

    whenの値を数える過程で、有効な4つの選択肢(before / after / async_always / before_display)のどれにも一致しない値を持つレコードが1件見つかりました。名前は「OnCallEscalation」、Globalスコープでcollectionは空、whenの値はactionです。sys_choiceの選択肢一覧にこの値は登録されておらず、フォームのドロップダウンからは選べないはずです。おそらく過去のバージョンで許可されていた値が、アップグレードをまたいで残存したものと考えられます。件数を単純にwhenでグループ化しただけでは、こうした非標準の値を見落とします。

    もう1つ意外だったのは、非推奨の内部値async(ラベル「旧async」)が54件から64件に増えていたことです。非推奨のはずの選択肢を使うBusiness Ruleが、標準機能のアップデートによって今も新規に増える余地がある、ということになります。非推奨だから0件に向かっていくとは限りません。


    実務では何に使える? 新しいBusiness Ruleを作るときに見るフィールド

    新しくBusiness Ruleを作るとき、あるいは既存のものを読み解くとき、見るフィールドは実質4つに絞れます。

    • when … 保存前に止めたい・直したいならbefore、保存後に他のレコードへ連携したいならafter、応答を待たせたくない重い処理ならasync、クライアントに値を渡すだけならdisplay

    • order … 既定の100のままで足りることが多く、他のBRとの前後関係が必要になったときだけ意図的にずらす

    • **action_* / filter_condition / condition** … まず反応するDB操作を絞り、宣言的フィルタで対象を絞り、必要なときだけJavaScriptの追加条件を書く

    • advanced … 単純な値セットで足りるならfalseのままtemplateを使い、条件分岐や計算が要るならtrueにしてscriptを書く

    既存のBusiness Ruleを調べるときは、対象テーブルのsys_script一覧をwhen・order順に並べれば、実行される順番のままフィールドを追えます。前述のsys_script_list.do?sysparm_query=collection=<テーブル名>^active=true^ORDERBYwhen^ORDERBYorderは、そのままチェックの起点として使えるURLです。


    まとめ

    Business Ruleは、sys_scriptという1つのテーブルに、1ルール=1レコードで保存されています。sys_metadata(Application File)配下の「アプリ構成」として管理される点が出発点で、業務データそのものではありません。

    いつ動くかはwhen、同じwhen内の順番はorder、実際に動くかどうかはaction_*→filter_condition→conditionという3段階のフィルタが決めます。今回のPDIではbeforeが全体の6割を占め、orderは84.6%が既定の100のままでした。処理本体を書くかどうかはadvancedフラグ次第で、ほぼ全件がscriptを直接書く高度モードです。

    次にBusiness Ruleを1件読み解くときは、まずwhenとcollectionで「いつ・どのテーブルに効くか」を確認します。そのうえでaction_*とfilter_condition / conditionから「どんな条件で動くか」を追えば、フォーム1枚から仕組みを読み切れます。答えは1レコードの中です。

    用語

    • PDI … Personal Developer Instance(無料の検証用インスタンス)

    • OOTB … Out of the Box(初期設定のまま)

    • Business Rule … レコード操作・照会時にサーバー側で動く処理の定義

    • sys_script … Business Ruleを格納するテーブル

    • collection … そのBRが紐づく対象テーブル名(画面ラベル: Table)

    • g_scratchpad … display BRでサーバー→クライアントへ値を渡すオブジェクト

    実機で調べるときに開いたURL

    • sys_db_object_list.do?sysparm_query=name=sys_script … テーブル定義

    • sys_choice_list.do?sysparm_query=name=sys_script^element=when^inactive=false^ORDERBYsequence … whenの選択肢

    • sys_dictionary_list.do?sysparm_query=name=sys_script^elementISNOTEMPTY … フィールド一覧

    • sys_script_list.do?sysparm_query=collection=incident^active=true^ORDERBYwhen^ORDERBYorder … incidentのBR

    • sys_script_list.do … 全BR一覧


    次に読むなら


    参考リンク


    検証環境と未検証範囲

    確認した範囲(PDI/Zurich/2026-08-08 再測定のOOTBで取得。初回確認は2026-06-21):

    • sys_scriptの継承(sys_metadata配下)

    • 固有フィールド数(34)

    • whenの選択肢(before/after/async/display)と件数、非標準の値(action・空欄)

    • advanced分布、action_*フラグ件数、abort_action件数

    • filter_condition / conditionの設定率

    • order分布

    • collection紐づき(incident / task / 空)

    確認していない範囲:

    • 各Business Ruleの内部スクリプトの実際の挙動

    • 継承テーブル(task→incident)での実行マージ順の実測

    • current / previous / g_scratchpadの実行時挙動

    • Client Script / UI Policyとの連携、Flow Designer / Script Includeとの実行順序

    • ドメイン分離環境での差異

    件数は2026-08-08時点の値です。本番環境やカスタマイズ済みの環境では、ルールの数・内容・実行順が異なります。

     
     
    ServiceNowのPDI(Personal Developer Instance)を実機で観察して、Noteに記事を書いています 実装・運用・教育の現場視点で淡々と記録中です リクエストがあればその記事も書きます 個人の観察日記です

    あなたへのおすすめ