Mastering Approval Workflows in ServiceNow: A Deep Dive
In the intricate world of IT Service Management (ITSM), robust and efficient approval workflows are the bedrock of controlled processes.
Whether it’s approving a change request, provisioning a new piece of software, or granting access to sensitive data, a well-defined approval
process ensures governance, minimizes risk, and maintains operational integrity. This article delves into a comprehensive, real-world
approval workflow scenario within ServiceNow, leveraging our collective experience across various versions to build a practical understanding.
We’ll explore the foundational elements, scripting best practices, and common challenges, providing actionable insights for both seasoned
professionals and those new to the platform.
Our journey starts from our latest experience with Washington D.C., building upon a strong foundation laid through
versions like Rome, San Diego, Tokyo, Utah, and Vancouver. This continuous evolution in ServiceNow means our understanding of
workflows is always being refined, ensuring we’re employing the most efficient and secure methods.
Understanding the Core Components: Users, Groups, and Permissions
At the heart of any ServiceNow workflow, especially approvals, lie users, groups, and the permissions (roles) assigned to them.
Effectively managing these is crucial for security and operational efficiency.
User and Group Management in ServiceNow
When we talk about managing who can do what in ServiceNow, we’re primarily dealing with users and the groups they belong to.
The sys_user table holds all our user accounts, and the sys_user_group table stores our organizational groups.
Best Practice for Permissions: Group-Based Role Assignment
A fundamental principle for managing permissions is to leverage groups. Instead of assigning roles directly to individual users,
the best practice is to assign roles to groups. When a user leaves the organization or changes roles, you simply remove them from the
relevant group(s), and their permissions are automatically revoked. This drastically simplifies administration and reduces the risk of
orphaned permissions.
We can, of course, create users and groups programmatically using scripts. Here’s a glimpse:
Creating a User Account via Script:
var userGr = new GlideRecord('sys_user');
userGr.initialize();
userGr.username = 'jdoe';
userGr.firstname = 'John';
userGr.lastName = 'Doe';
userGr.email = 'jdoe@example.com';
userGr.insert();
Creating a Group via Script:
var newGr = new GlideRecord('sys_user_group');
newGr.initialize();
newGr.name = 'testing';
newGr.manager = '62826bf03710200044e0bfc8bcbe5df1'; // Replace with actual manager sys_id
newGr.email = 'testing@tcs.com';
newGr.description = 'test';
newGr.insert();
Similarly, we can add users to groups and vice-versa:
Adding a Group Member via Script:
var grMem = new GlideRecord('sys_user_grmember');
grMem.user = '62826bf03710200044e0bfc8bcbe5df1'; // User's sys_id
grMem.group = '477a05d153013010b846ddeeff7b1225'; // Group's sys_id
grMem.insert();
Removing a Group Member via Script:
var grMem = new GlideRecord('sys_user_grmember');
grMem.addQuery('user', '62826bf03710200044e0bfc8bcbe5df1'); // User's sys_id
grMem.addQuery('group', '477a05d153013010b846ddeeff7b1225'); // Group's sys_id
grMem.query();
if (grMem.next()) {
grMem.deleteRecord();
}
Assigning Roles and Permissions
Permissions in ServiceNow are managed through roles. When a role is assigned to a user or a group, specific capabilities are granted.
Assigning roles to users and groups can be done manually through the platform, but scripting offers immense flexibility for automation.
When a role is associated with a user, a record is created in the sys_user_has_role table. For groups, it’s the
sys_group_has_role table.
Adding a Role to a User via Script:
var userRole = new GlideRecord('sys_user_has_role');
userRole.setValue('user', '62826bf03710200044e0bfc8bcbe5df1'); // User's sys_id
userRole.setValue('role', '2831a114c611228501d4ea6c309d626d'); // Role's sys_id
userRole.insert();
Adding a Role to a Group via Script:
var grpRole = new GlideRecord('sys_group_has_role');
grpRole.setValue('group', '477a05d153013010b846ddeeff7b1225'); // Group's sys_id
grpRole.setValue('role', '2831a114c611228501d4ea6c309d626d'); // Role's sys_id
grpRole.insert();
Interview Relevance: Understanding user and group management, table names (sys_user, sys_user_group, sys_user_grmember),
and role assignment tables (sys_user_has_role, sys_group_has_role) is fundamental. Be ready to discuss the best practice of group-based
role assignment.
User Delegation: Ensuring Business Continuity
What happens when an essential approver goes on vacation or is otherwise unavailable? This is where user delegation
shines. It allows one user to perform tasks and act on behalf of another within the platform.
User delegation is a powerful feature for ensuring that critical processes, especially approvals, don’t stall when a user is out.
The delegated user gains the necessary permissions to act on behalf of the original user, including handling assignments, receiving
notifications, and crucially, approving or rejecting requests.
Configuring delegation is straightforward: navigate to the original user’s record, scroll down to the “Delegates” related list,
and specify the delegate, the effective dates, and the scope of delegation (assignments, notifications, approvals).
Interview Relevance: Be prepared to explain what user delegation is, its importance for business continuity, and
how it’s configured within ServiceNow. Providing a real-world example (like an approver on vacation) is always beneficial.
Deep Dive into ServiceNow Workflows: Incident, Problem, and Change Management
ServiceNow’s ITSM capabilities are largely built around managing core IT services. Understanding how these processes interact is
key to designing effective approval workflows.
Incident Management: Restoring Service Swiftly
An incident is defined as a disruption to a normal IT service that impacts the user’s ability to work. When an employee
encounters an issue – say, their email client stops working – they typically log an incident to get support.
Troubleshooting Tip: If you’re struggling to create an incident via script, double-check the sys_ids for
‘caller_id’, ‘assignment_group’, and ‘cmdb_ci’. Incorrect sys_ids are a common culprit.
Creating an Incident Record via Script:
var gr = new GlideRecord('incident');
gr.initialize();
gr.caller_id = '86826bf03710200044e0bfc8bcbe5d94'; // Caller's sys_id
gr.category = 'inquiry';
gr.subcategory = 'antivirus';
gr.cmdb_ci = 'affd3c8437201000deeabfc8bcbe5dc3'; // CI's sys_id
gr.short_description = 'test record using script';
gr.description = 'test record using script';
gr.assignment_group = 'a715cd759f2002002920bde8132e7018'; // Assignment Group's sys_id
gr.insert();
Problem Management: Tackling Recurring Issues
When the same incident or similar issues repeatedly affect users, it escalates to a problem. The goal of problem management
is to identify the root cause of these recurring incidents and prevent them from happening again. If an issue impacts multiple users
simultaneously, it’s often treated as a major incident, with other affected users’ reports linked as child incidents.
Creating a Problem Record via Script:
var gr = new GlideRecord('problem');
gr.initialize();
gr.caller_id = '86826bf03710200044e0bfc8bcbe5d94'; // Caller's sys_id
gr.category = 'inquiry';
gr.subcategory = 'antivirus';
gr.cmdb_ci = 'affd3c8437201000deeabfc8bcbe5dc3'; // CI's sys_id
gr.short_description = 'test record using script';
gr.description = 'test record using script';
gr.assignment_group = 'a715cd759f2002002920bde8132e7018'; // Assignment Group's sys_id
gr.insert();
Change Management: Implementing Controlled Modifications
A change request is initiated when a modification to the IT infrastructure or services is required. This could be a software update,
hardware replacement, or configuration change. The purpose is to minimize disruption and risk associated with these changes.
Crucially, both incidents and problems can lead to the creation of change requests if the support team identifies that a systemic fix
requires a change in the environment.
Creating a Change Request via Script:
var gr = new GlideRecord('change_request');
gr.initialize();
gr.category = 'inquiry';
gr.subcategory = 'antivirus';
gr.cmdb_ci = 'affd3c8437201000deeabfc8bcbe5dc3'; // CI's sys_id
gr.short_description = 'test record using script';
gr.description = 'test record using script';
gr.assignment_group = 'a715cd759f2002002920bde8132e7018'; // Assignment Group's sys_id
gr.insert();
Relationship between Incident, Problem, and Change: In essence, if a user faces an issue (Incident), and it’s a recurring
problem, we investigate its root cause (Problem). If resolving the root cause requires altering the system, we initiate a formal
modification process (Change Request).
Interview Relevance: Be clear on the definitions of Incident, Problem, and Change Request. Understand the lifecycle and
how they can relate to each other (e.g., creating a Problem from an Incident, or a Change from either).
Automating Workflow Logic with Business Rules and Scripts
ServiceNow’s power lies in its automation capabilities. Business Rules and Client Scripts are the primary tools for embedding logic into workflows.
Automating Child Incident Closure
A common requirement is to ensure that when a parent incident is closed, all associated child incidents are also closed to maintain data integrity.
This is elegantly handled by an “After” Business Rule.
Business Rule Logic to Close Child Incidents:
// When -- After
// Update -- true
// Condition: current.state.changesTo(7); // Assuming state 7 is 'Closed'
if (current.state == 7 && current.parent == '') { // Check if it's closed and a parent incident
// GlideRecord to find child incidents
var grChild = new GlideRecord('incident');
grChild.addQuery('parent', current.sys_id);
grChild.query();
while (grChild.next()) {
grChild.state = 7; // Set the state to Closed
grChild.update(); // Update the child incident
}
}
Troubleshooting Tip: If child incidents aren’t closing, verify the exact state value for ‘Closed’ in your instance.
Also, ensure the Business Rule is correctly configured to run “After” an update and that the condition precisely matches the state change.
Preventing Incident Closure with Open Tasks
To ensure thoroughness, we often want to prevent the closure of an incident (or problem/change) if there are still open tasks associated with it.
This is typically achieved with a “Before” Business Rule to abort the action.
Business Rule Logic to Prevent Closure with Open Tasks:
// When -- Before
// Update -- true
// Condition: current.state.changesTo(7); // Assuming state 7 is 'Closed'
var grTask = new GlideRecord('incident_task'); // Or 'problem_task', 'change_task'
grTask.addQuery('incident', current.sys_id); // Link to the current record
grTask.addQuery('state', '!=', 3); // Assuming state 3 is 'Closed'
grTask.query();
if (grTask.hasNext()) {
gs.addErrorMessage('Cannot close the incident because there are open tasks.');
current.setAbortAction(true);
}
Automating Incident Closure from Problem Closure
Similarly, when a problem is resolved and closed, it’s logical to close all associated incidents that were direct results of that problem.
This can also be managed with an “After” Business Rule on the problem table.
Business Rule Logic to Close Incidents from Problem Closure:
// When -- After
// Update -- true
// Condition: current.state.changesTo(7); // Assuming state 7 is 'Closed'
if (current.state == 7) { // Check if the problem is closed
// GlideRecord to find incidents associated with the problem
var grIncident = new GlideRecord('incident');
grIncident.addQuery('problem_id', current.sys_id); // Link to the problem
grIncident.addQuery('state', '!=', 7); // Assuming 7 is the state value for 'Closed'
grIncident.query();
while (grIncident.next()) {
grIncident.state = 7; // Set the state to Closed
grIncident.update(); // Update the incident
}
}
Interview Relevance: Be ready to discuss Business Rules (Before, After, Display), their conditions, and scripting for automation.
Understanding how to abort actions and use ‘gs.addErrorMessage’ is key.
Understanding ServiceNow Table Structure and Design
A solid grasp of ServiceNow’s data model is essential for effective configuration and development.
Out-of-the-Box (OOB) and Base Tables
Out-of-the-Box (OOB) tables are those that come pre-installed with ServiceNow and do not start with ‘x_’ (custom applications)
or ‘u_’ (legacy custom applications). Examples include ‘incident’, ‘problem’, and ‘change_request’.
Base tables are foundational tables that are often extended by other tables. They serve as a common parent. The ‘task’ table is a prime example,
as ‘incident’, ‘problem’, and ‘change_request’ all extend it, inheriting common fields. The ‘cmdb_ci’ table is another crucial base table for Configuration Management.
Interview Relevance: Differentiate between OOB tables and custom tables. Know what base tables are and why they are important, with examples like ‘task’.
Table Extension and Inheritance
When you extend a table, the child table inherits all fields and attributes from its parent. This means you don’t need to redefine common fields like ‘sys_created_on’ or ‘sys_updated_by’ in the child table. A ‘class’ field is automatically created in the parent table to track which specific child table the record belongs to, especially when a table extends multiple other tables.
Troubleshooting Tip: If a field you expect to see isn’t present on a custom table, check if it’s inherited from a parent table.
You might need to create a dictionary override if you want to modify its behavior specifically for the child table.
Table Attributes and Field Types
ServiceNow offers a rich set of field types to cater to various data requirements. Here are a few examples:
Reference, String, List, Choice, Email, Date/Time, Date, Boolean, Integer, Journal, Attachment.
Attributes are special directives applied at the dictionary level to modify field behavior. For instance, ‘no_email’ prevents
email notifications for changes to that field, ‘no_attachment’ disables attachments for that record type, and ‘tree_picker’ enables a hierarchical selection.
Interview Relevance: Be able to list common field types and provide examples of attributes and their use cases.
Default Values and Calculated Fields
You can set default values for fields, ensuring they are pre-populated when a record is created. For dynamic values,
calculated fields are used, where the field’s value is determined by a script, often utilizing the ‘current’ object.
Setting Field Values with `current` Object (Server-side):
// Setting a value
current.setValue('field_name', 'some_value');
// Setting a display value for a reference field (shows the text, not sys_id)
current.setDisplayValue('reference_field_name', 'Display Text');
The ‘current’ object is a powerful server-side tool in Business Rules, Script Includes, and other server-side scripts.
It represents the record being processed, allowing you to get and set field values.
Collection Fields
Dictionary entries of the ‘Collection’ type represent the table itself, not a specific field. Attributes applied here affect the entire table.
For example, adding the ‘no_attachment’ attribute to the collection field entry for the ‘incident’ table will disable attachments for all incident records.
Dictionary Overrides
When you need to alter a field’s behavior for a child table differently than its parent, you use dictionary overrides.
For example, changing the default value of the ‘priority’ field in the ‘Incident’ table from what’s defined in the parent ‘Task’ table.
Controlling User Interface and Data Behavior
ServiceNow provides robust mechanisms to control how users interact with forms and how data is validated and displayed.
UI Policies vs. Data Policies
UI Policies operate on the client-side and are excellent for controlling field visibility, making fields mandatory or read-only,
and showing/hiding related lists dynamically as the user interacts with the form. The ‘Global’ checkbox determines if the policy applies
across all views, and ‘Reverse if false’ ensures actions are undone when conditions are no longer met. The ‘On Load’ checkbox triggers
the policy when the form initially loads.
Data Policies, on the other hand, enforce data consistency at both the client and server sides, ensuring data integrity regardless
of how the record is accessed (form, API, etc.). They can also make fields mandatory or read-only.
You can convert UI Policies to Data Policies (and vice-versa in some cases) using platform tools. However, UI Policies are better suited for
controlling view-specific behavior, controlling related lists, or executing complex client-side scripts.
Troubleshooting Tip: If a UI Policy isn’t behaving as expected, check its conditions, related UI Policy Actions, the ‘Global’ flag,
and ensure it’s not being overridden by another policy or client script. For Data Policies, remember they work server-side too, so client-side issues might not be the cause.
Interview Relevance: Clearly articulate the differences between UI Policies and Data Policies, their scope, and common use cases.
Understand the implications of checkboxes like ‘Global’, ‘Reverse if false’, and ‘On Load’.
Mandatory and Read-Only Fields
Fields can be made mandatory or read-only through various methods:
- Dictionary properties
- Dictionary Overrides
- UI Policies
- Data Policies
- Client Scripts (using
g_form.setMandatory()org_form.setReadOnly())
Important Note: You should generally only have one ‘Display’ field per table. Having multiple can lead to user confusion.
Advanced Reference Field Management
Reference fields are crucial for linking records. Reference Qualifiers allow us to refine the list of records that can be selected.
Types of Reference Qualifiers:
- Simple: Uses direct query conditions (e.g.,
active=true). - Dynamic: Leverages pre-configured dynamic filter options for context-aware filtering.
- Advanced: Utilizes custom JavaScript to define complex filtering logic, offering the most flexibility.
Example: If you have a ‘Configuration Item’ field on an Incident form, a simple reference qualifier might restrict it to ‘Active’ CIs.
A dynamic qualifier could show CIs related to the caller’s department. An advanced qualifier could filter based on CIs that have had incidents logged against them in the last 30 days and are owned by a specific group.
Interview Relevance: Be able to explain the purpose of reference qualifiers and differentiate between simple, dynamic, and advanced types,
providing examples for each.
Dependent Values
Dependent values create cascaded dropdowns. For example, selecting a ‘Category’ (e.g., ‘Hardware’) in one field dynamically filters the choices
available in the ‘Subcategory’ field (e.g., showing ‘Laptop’, ‘Printer’ instead of ‘Software’ options). This is configured by linking the
dependent field’s dictionary entry to the parent field.
Understanding ServiceNow’s Data Storage and Retention
ServiceNow stores all its table definitions in the sys_db_object table. Understanding how data is stored and retained is vital for
performance and compliance.
Temporary vs. Normal Tables
Temporary tables are designed for short-term data storage, often used for import sets. They typically extend the
‘import_set_row’ table and retain data for a limited period (often 7 days, but this can be extended using archive rules).
Normal tables store data permanently until explicitly deleted.
Remote Tables
Remote tables provide a way to access live data from external data sources directly within ServiceNow without importing it.
This contrasts with normal tables, which store data locally within the ServiceNow instance.
Relationships: One-to-One and One-to-Many
Understanding table relationships is key to building effective integrations and data models.
- One-to-Many: A single record in one table can be related to multiple records in another. Example: One ‘User’ can have many ‘Incidents’.
- Many-to-Many: Records in two tables can be related to multiple records in each other. Example: An ‘Incident’ can be assigned to multiple ‘Groups’, and a ‘Group’ can be assigned to multiple ‘Incidents’.
Record Creation Methods
Records can be created in ServiceNow tables through various methods:
- Record Producers
- Email (inbound actions)
- GlideRecord scripting
- Forms
- Excel sheet imports
- External systems (via APIs like REST)
Application Menus and Process Flow
Application Menus are used to create modules within ServiceNow, making forms and lists accessible to end-users through the navigation
menu.
Process Flow visually indicates the current stage of a record within a workflow, providing users with context on where they are in a process.
Access Control Lists (ACLs)
Access control is fundamental to security. When a table is created, by default, four Access Control Lists (ACLs) are generated to
manage read, write, create, and delete operations. This can be bypassed by unchecking a specific option during table creation.
The security_admin role is required to work with and manage ACLs.
Impersonation and Testing
Impersonation is a critical testing tool that allows administrators to log in as another user. This is invaluable for verifying
that roles, ACLs, and UI policies are functioning correctly from an end-user’s perspective.
Conclusion
Mastering approval workflows in ServiceNow is an ongoing journey that blends technical expertise with a deep understanding of business processes.
By leveraging the platform’s robust features for user and group management, scripting automation, data control, and table design, organizations can
build highly efficient, secure, and auditable workflows. This comprehensive overview, grounded in practical experience across multiple ServiceNow versions,
aims to equip you with the knowledge to navigate and optimize these critical processes.
- Are the correct roles assigned to users and groups?
- Are Business Rules, UI Policies, or Data Policies interfering with each other?
- Are there any client scripts or server-side scripts causing unexpected behavior?
- Are the conditions for your logic correctly defined?
- For scripting, are sys_ids accurate?
- Check the System Logs for errors.