Business Rules

Business Rules ServiceNow : Le Guide Complet du Développeur (2026)

Tout ce que vous devez savoir sur les Business Rules ServiceNow : types, déclencheurs, ordre d’exécution, bonnes pratiques et exemples de code concrets. La référence pour consultants et développeurs.

Les Business Rules sont l’un des outils les plus puissants — et les plus mal utilisés — de la plateforme ServiceNow. Mal écrites, elles sont à l’origine d’innombrables incidents de production : boucles infinies, performances dégradées, comportements imprévisibles à la mise à jour. Bien écrites, elles sont la colonne vertébrale d’une instance maintenable.

Ce guide condense ce qu’un consultant doit absolument savoir en 2025 : quand utiliser une Business Rule, quel type choisir, comment écrire le script, et surtout quelles erreurs évitent un week-end à débugger.

Qu’est-ce qu’une Business Rule ?

Une Business Rule est un script côté serveur, déclenché par un événement de base sur une table donnée : insertion, mise à jour, suppression, ou requête. Contrairement à un Client Script (qui s’exécute dans le navigateur), une Business Rule a accès complet à l’API serveur — donc à GlideRecordgs.log, aux Script Includes, etc.

L’équivalent dans d’autres mondes : un trigger SQL, mais avec la puissance d’un environnement applicatif complet.

 

Citation

Règle d’or : si vous pouvez le faire avec une Flow, une Data Policy ou une UI Policy, faites-le avec ça. Une Business Rule n’est justifiée que pour la logique qui doit s’exécuter quel que soit le canal d’entrée (UI, API, import, intégration).

 

Les 4 types : Before, After, Async, Display

Before

Exécutée avant la persistance. C’est ici qu’on modifie current sans coût (pas d’update() nécessaire). Idéal pour : valeurs par défaut, normalisation, calculs dérivés, validation bloquante avec current.setAbortAction(true).

 

Important

// Before insert/update on incident
// Normaliser la priorité en fonction de l’urgence + impact
(function executeRule(current, previous /*null when async*/) {
if (current.urgency.changes() || current.impact.changes()) {
current.priority = computePriority(current.urgency, current.impact);
}
})(current, previous);

 

After

Exécutée après la persistance. current a déjà l’ID définitif et est en base. Idéal pour : créer des enregistrements liés, déclencher une notification, journaliser, mettre à jour une autre table.

Attention

Ne modifiez pas current dans une After sans appeler current.update() — sinon vos changements sont perdus.

Async

Comme After, mais découplée : exécutée par le scheduler dans une transaction séparée. C’est le bon choix dès que la logique n’a pas besoin d’être visible immédiatement à l’utilisateur (envoi d’email, sync vers un système externe, calcul lourd).

Display

Exécutée au chargement du formulaire. Sert principalement à pousser des données dans g_scratchpad à destination des Client Scripts (typiquement, des résultats de Script Include nécessaires côté UI).

 

Important

// Display Business Rule
(function executeRule(current, previous) {
g_scratchpad.userIsManager = gs.getUser().hasRole(‘itil_admin’);
g_scratchpad.relatedTickets = new IncidentUtils().countOpenForCaller(current.caller_id);
})(current, previous);

 

When to run : conditions et déclencheurs

Le champ When détermine quand le script tourne ; le champ Filter Conditions détermine sur quels enregistrements. Quelques règles de bon sens :

Important
  • Préférez les Filter Conditions au if en début de script : c’est filtré côté DB, donc plus rapide.
  • N’utilisez Insert + Update que si la logique est strictement identique. Sinon, séparez en deux Business Rules nommées clairement.
  • Le combo Async + Update sur une table à fort volume (incident, task) est un grand classique du noisy neighbor : si vous le faites, vérifiez le coût avec System Diagnostics → Stats.

Ordre d’exécution et priorités

L’ordre des Business Rules sur une même table suit le champ order (ascendant). Les valeurs par défaut sont 100 et 200 ; conservez 0–999 pour vos rules métier et réservez 1000+ pour les rules transverses (audit, sync). Documentez l’ordre dans la description — futur-vous vous remerciera.

Étape Type Conseil
1 Before Validation, normalisation, valeurs dérivées
2 Persistance (automatique)
3 After Effets côté DB nécessaires immédiatement
4 Async Effets différés, externes, lourds

Exemples concrets commentés

Exemple 1 — Empêcher la fermeture d’un incident sans description de résolution

Astuce

// Type: Before, When: update, Filter: state changes to Resolved
(function executeRule(current, previous) {
if (gs.nil(current.close_notes)) {
gs.addErrorMessage("Vous devez renseigner les notes de résolution avant de fermer.");
current.setAbortAction(true);
}
})(current, previous);

Exemple 2 — Auto-assignation au manager de la CI lors de la création

Astuce

// Type: Before, When: insert, Filter: cmdb_ci is not empty AND assigned_to is empty
(function executeRule(current, previous) {
var ci = new GlideRecord('cmdb_ci');
if (ci.get(current.cmdb_ci.toString())) {
if (!gs.nil(ci.managed_by)) {
current.assigned_to = ci.managed_by;
current.assignment_group = ci.support_group;
}
}
})(current, previous);

Exemple 3 — Async : notifier un système externe via Scripted REST

Astuce

// Type: Async, When: after insert OR update
// Délègue toute la logique à un Script Include — la BR reste mince.
(function executeRule(current, previous) {
new x_corp_sync.IncidentMirror().push(current.getUniqueValue());
})(current, previous);

Pièges classiques à éviter

  • Boucle infinie sur current.update() dans une After. Si vous appelez update(), la BR se redéclenche. Solution : guardez avec current.changes() ou utilisez Before.
  • setWorkflow(false) oublié. Quand vous mettez à jour une autre table, désactivez le workflow et les Business Rules cibles si elles ne sont pas pertinentes — sinon vous cascadez sans le vouloir.
  • Logique métier dans la BR plutôt que dans un Script Include. Une BR doit appeler ; pas implémenter. C’est la seule façon de tester unitairement.
  • Pas de previous dans Async. Le param previous est null dans une Async — utilisez current.changes() avec prudence (elle compare à la valeur en DB au moment de l’exécution, pas au moment du déclenchement).
  • Trop de BR sur une même table. Au-delà de ~30 BR actives sur une table chaude (incident, task), regroupez ou migrez vers Flow Designer.

Bonnes pratiques de production

  1. Nommez clairement. Incident — auto-assign from CI manager bat BR1.
  2. Une responsabilité par BR. Si la description fait plus de deux phrases, divisez.
  3. Délégez aux Script Includes. Le script de la BR doit tenir en moins de 20 lignes idéalement.
  4. Tracez avec gs.info(). Pas gs.log() — on le retrouve mieux dans les System Logs.
  5. Désactivez plutôt que supprimer. Une BR désactivée garde son historique d’audit.
  6. Update Set discipline. Une BR par Update Set quand c’est possible — ça facilite les rollbacks.

FAQ rapide

Quand utiliser une Flow plutôt qu’une Business Rule ?

Si la logique est linéairevisualisable et maintenable par un fonctionnel, choisissez Flow Designer. Pour de la logique pure code (calculs, manipulation de données complexes, intégrations), Business Rule reste plus adapté.

Comment tester une Business Rule ?

Trois leviers : gs.info() dans le script + System Logs, Background Scripts pour exécuter le code à la main, et surtout : déléguez la logique à un Script Include et testez celui-ci avec ATF.

Async ou After ?

Si l’utilisateur n’a pas besoin du résultat immédiatement (et que ça ne casse pas un workflow visible), Async. Sinon After.

admin.aly

About Author

Leave a comment

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *