- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
02-04-2023 06:06 AM - edited 05-23-2025 12:33 AM
If you want to get notified when new Business Rules are added by me, you can subscribe to this page!
Over time, every developer or system administrator builds little helpers that make working with ServiceNow more convenient and secure. This is also true for me, and in this article I present a few Business Rules that have been collecting in my toolbox.
What are Business Rules?
Business Rules are server-side logic that execute when database records are queried, updated, inserted, or deleted. Business Rules respond to database interactions regardless of access method: for example, users interacting with records through forms or lists, web services, or data imports (configurable). They do not monitor forms or form fields but do execute their logic when forms interact with the database such as when a record is saved, updated, or submitted.
Please refer to the ServiceNow documentation pages if you want to learn more about Business Rules. |
Prevent direct assignments of licensable roles to users
Except for the admin user, the following Business Rule prevents a licensable role from being assigned directly to a user. If you are interested: I have written a separate article on the underlying reasons.
Business Rule
Table |
sys_user_has_role |
Advanced |
true |
When |
before |
Insert |
true |
Filter Conditions |
|
Script |
|
Prevent adding artifacts to an update set which is not "In Progress" state
I experienced inexplicable affects on a ServiceNow instance where a release had recently been deployed the other day within one of my projects. After a long investigation, it was identified that one of the deployed Update Sets contained an artifact that had been inserted after the Update Set was already closed. Yes, you read that correctly. ServiceNow does not restrict the addition of artifacts to an already closed Update Set.
However, you can avoid this with a simple Business Rule on the sys_update_xml table and spare yourself a lot of hassles.
Business Rule
Table |
sys_update_xml |
Advanced |
true |
When |
before |
Update |
true |
Filter Conditions |
|
Script |
|
Force creation of personal artifacts in the "Global" scope
Have you ever noticed these strange artifacts (aka application files) in your app?
In ServiceNow, there are a number of artifact types that, although personal in nature, have an "Application" column and are thus captured in applications.
This happens, for example, whenever a user personalizes a list and happens to select an application under development in the Application Picker.
This is where the following business rule comes into play: If one of the three artifact types I have identified so far is to be created and the target application is not "Global", the creation in the Global Scope is enforced accordingly.
Business Rule
Table |
sys_metadata |
Advanced |
true |
When |
before |
Order |
10000 |
Insert |
true |
Filter |
|
Actions |
Prevent sending of unwanted emails
A fresh ServiceNow instance already has tons of activated email notifications, and each new plugin you are going to install might be shipped with additional ones.
Most system administrators would iterate the list and deactivate all notifications which are not required. But this approach has several downsides:
- This blacklist approach is rather time-consuming and with every new installed plugin you have to check again all new notifications.
- There is a risk of creating so-called "skipped records" for all of these deactivated notifications in the next system upgrade.
- All deactivations have to be captured in an update set to provision these changes to all other instances.
Instead, use a whitelist approach to let the system send only emails from allowed notifications. Such a whitelist could for example be maintained via a system property. And then you need the following Business Rule which identifies the underlying notification for an email to be sent. If the notification doesn't pass the whitelist, the respective email record is set to "send-ignored".
Business Rule
⚠️ Please note:
The script part in the following Business Rule has to be modified first according to your needs before you can use it. My below example will ignore all emails with notification records in the "global" scope.
Table |
sys_email_log |
Advanced |
true |
When |
after |
Insert |
true |
Script |
|
Set agent's availability automatically
If you have installed the plugin Advanced Work Assignment in your instance, agents can set their presence status to "Available" in the inbox module of any workspace to indicate they are ready for receiving tickets:
And as most of the agents are just working in ServiceNow by dealing with any assigned work, they are asking to set the presence status automatically.
The following Business Rule will do this by catching the login and writing the status to table awa_agent_presence accordingly.
Business Rule
Table |
sys_user |
Advanced |
true |
When |
async |
Update |
true |
Filter |
|
Condition |
|
Script |
|
Reduce syslog list results to the last 15 minutes
Depending on which instance you are, what the configured log level is and how many log outputs your applications are creating, the number of records in the syslog table can be many millions large. Opening such a large table via "syslog.list" in the application navigator will block your session for some time or even cancel the transaction.
Therefore, it is better to enter "syslog.filter", which prevents the initial loading of the data and allows you to configure a filter accordingly instead. For example, you can specify that only records created in the last 15 minutes should be returned.
But how many times have you been unaware of this? For this reason, the following "before query" Business Rule checks whether a filter expression has been configured for the sys_created_on field. If not, a filter expression is added that restricts the results to those created in the last 15 minutes. You can override this restriction by explicitly configuring a filter expression for the sys_created_on field.
Business Rule
Table |
syslog |
Advanced |
true |
When |
before |
Query |
true |
Condition |
|
Script |
|
Display all suites an instance scan check is contained in
Scan Checks in ServiceNow are related to any Scan Suites via the many-to-many table. For this reason, you cannot configure a corresponding related list on a Scan Check form. OOTB ServiceNow provides a Relationships "Check" you could configure instead:
But honestly that's not the best user experience as you have to scroll down each time you open a Scan Check. However, I need this information right at the beginning of the form, so I wrote the following "display" business rule, which displays the list of all referencing Scan Suites:
Business Rule
Table |
scan_check |
Advanced |
true |
When |
display |
Condition |
|
Script |
|
Display a warning in case an OOTB artifact has been modified
Changing OOTB artifacts like Script Includes or Business Rules is never a good idea, as you will get so called skipped records in the next upgrade/patch you have to care about. Otherwise, you can get into big trouble and risk broken functionalities as well as unpredictable behavior. But many developers are not aware about the consequences when playing around with OOTB artifacts or know how to revert the changes (see https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0993700 if you don't know how).
Therefore I thought it is helpful to display a warning when opening a modified OOTB artifact and built the following Business Rule. The warning message also provides a link to the most recent OOTB version, where you will find a UI Action for reverting to that version.
Within the script I have avoided using APIs here, which are not available in Scoped Apps, so you can adopt the business rule more easily. Furthermore I have narrowed down the scope to displaying forms in he Classic UI but feel free to adopt to Workspaces or Service Portals as well.
Business Rule
Table |
sys_metadata |
Advanced |
true |
When |
display |
Condition |
|
Script |
|
Block large Profile Pictures
In ServiceNow users can add a picture to their personal profile record (table sys_user), which is then used as an avatar image everywhere. Basically, you probably wouldn't give it a second thought, but the problem here is that there are no size limits OOTB nor are thumbnails automatically generated from these images. However, if a larger number of these images is used somewhere (e.g. EVAM-based cards for agents to be dispatched in the FSM Dispatcher Workspace), the files are loaded in their original size, although they are actually only needed in a very small version. The consequence is a massive performance decrease due to the long loading times for all the oversized profile pictures. For this reason, it is a good idea to make sure that profile pictures do not exceed a certain file size.
Business Rule
⚠️ Please note:
The following Business Rule utilizes a System Property max_profile_picture_file_size to define the maximum file size.
Table |
sys_attachment |
Advanced |
true |
When |
before |
Filter Conditions |
|
Insert |
true |
Script |
|
Display a warning if an artifact was skipped
Skipped records are a major annoyance in ServiceNow. And I am not referring to skipped records for changed OOTB artifacts, but those that arise after the deployment of custom applications via the application repository. If the processing of skipped records does not become an integral part of your deployment process, you run the risk of your instances deviating more and more from each other unnoticed and thus a flood of bug tickets is guaranteed. For this reason, the following business rule checks the sys_upgrade_history_log table when an artifact record is opened to see whether there is currently a skipped record for it and generates a corresponding warning message accordingly if this applies.
Business Rule
Table |
sys_metadata |
Advanced |
true |
When |
display |
Script |
|
Add Relationships "Updates" & "Versions" automatically to the Form
Whenever you change an artifact (configuration records - not data!) you automatically create a new version (table sys_update_version) and in most of the cases also a record at table sys_update_xml which might be captured in an update set. For code reviews, I therefore always scroll to the related lists section first to check whether the "Updates" & "Versions" Relationships have been added. And I was quite tired of manually adding these two Relationships to the form every time, because they are practically nowhere to be found in a baseline version. Therefore, each time a record from a child table of sys_metadata is changed, the following Business Rule checks whether the two Relationships are present in the current view and adds them if necessary. In order not to interfer with any application the related configurations are created in the "global" scope.
Business Rule
Table |
sys_metadata |
Advanced |
true |
When |
before |
Insert |
true |
Update |
true |
Condition |
|
Script |
|
Warn if translations are missing for the name of the UI Action
In a multilingual ServiceNow instance, translations need to be added in many places and distributed across the five designated tables. One UI element where missing translations are particularly noticeable is UI Actions. As a developer, it's easy to overlook that after spending hours working on a complex UI Action, the name also needs to be translated (table sys_translated) so that the links and buttons generated on the interface will appear to users in their respective languages. The following business rule helps by displaying a warning if translations are missing for any language other than the system default language. As an additional help, the displayed language names are linked to pre-populated pages where the missing translations can be created.
Business Rule
Table |
sys_ui_action |
Advanced |
true |
When |
display |
Condition |
|
Script |
|
Enforce Capturing of Scheduled Scripts for Committing to Git
The dictionary attribute update_synch is a key property that controls which tables have their changes tracked and captured in table sys_update_xml. If the attribute is missing or set to "false", changes to records in that table will not be captured in table sys_update_xml, the standard for raw data like incidents or locations. Tables that extend the sys_metadata table - the so-called configuration artifacts - are captured automatically unless there is a dictionary attribute update_synch=false configured for the corresponding table (and its child tables). This rare case exists for the table sysauto and all of its child tables like sysauto_script (Scheduled Script Execution). As a consequence such records cannot be committed to a Git respository as the commit sets are built based on the changes tracke in the sys_update_xml table. However with the help of Business Rule you can enforce creating a corresponding record in table sys_update_xml by leveraging the same approach like the well-know utility "Add to Update Set".
Business Rule
Table |
sysauto_script |
Advanced |
true |
When |
after |
Insert |
true |
Update |
true |
Script |
|
- 18,247 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks @Maik Skoddow

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Very useful -- thanks so much, Maik.
I wanted to call attention to your "Force Creation of personal Artifacts in "Global" Scope" business rule, I think the table listed in your article is incorrect. It isn't "sys_app" but rather "sys_metadata" table.
Cheers and thanks again!
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @chrisperry
Wow, that's awesome!
Many thanks for finding that error.
There are not very many people in this world who would see that right away.
Maik
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for sharing @Maik Skoddow
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for sharing great article. I tried your query BR for syslog table to restrict logs to 15 mins in PDI. I am always getting a blank page without any records. But I checked by direct query of last 15 mins in syslog table and I am able to see logs. Is there anything that needs to be updated from my end, Please advise.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for sharing great article.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Nothing short of amazing !
Greatly appreciated @Maik Skoddow !

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Maik Skoddow might be good to replace those gs.getMessage() methods for concatenating strings with template strings that are now available to us with ES12, e.g.: `Hello ${first_name}`.
ServiceNow support reprimanded me on my previous project for using gs.getMessage(), as each time that method is called, servicenow executes a resource-costly query of the sys_ui_message table for translation purposes. 😀