Managing roles in large ServiceNow environments can create performance challenges that don't show up until you're dealing with a genuinely large group. One common trigger: removing a role from a group containing thousands of users.
I recently ran into this with a group of more than 20,000 users that had an incorrect role assigned. Removing the role through the UI consistently timed out. This article covers why that happens and how to remove it safely.
The Problem
A role was mistakenly assigned to a group with more than 20,000 users. The role also had several child roles, which multiplied the number of permission recalculations needed across the platform.
Attempting to remove the role through the UI, or through a synchronous Fix Script, consistently resulted in timeout errors. The core issue: removing the role triggers role recalculation for every user in the group, all within the same request.
Why the Timeout Happens
When a role is removed from a group, ServiceNow re-evaluates role inheritance for every member of that group. The inheritance chain looks roughly like this:
User
↓
User Group
↓
Group Role (sys_group_has_role)
↓
Inherited Roles
↓
User Role Updates
With tens of thousands of users, that recalculation — done synchronously, inside a single UI transaction — can easily exceed the platform's request execution limits and time out before it finishes.
The Fix: Asynchronous Group Role Updates
ServiceNow has a system property that moves group role updates to a background job instead of processing them inside the UI request:
glide.ui.schedule_slushbucket_save_for_group_roles = true
Check this before assuming you need to set it — on most current instances, this property now ships enabled by default rather than needing to be turned on manually. Search sys_properties.list for it and confirm its current value before changing anything.
When it's enabled, adding or removing roles on a group is handed off to a scheduled background job rather than processed in your session. That's what avoids the timeout — but it also means the change isn't instant. You'll typically see an informational banner at the top of the group form, and you'll need to refresh to confirm the update actually completed.
A few things worth knowing before you rely on it:
- It doesn't apply to changing a group's Parent field. If your timeout is happening on a parent-group change rather than a role change, this property won't help — that's a separate, documented limitation.
- It can interact awkwardly with certain HR-scoped roles. Some administrators have hit cases where adding a user with an HR role to a group silently fails while this property is enabled, requiring a temporary toggle off, then back on, to complete the change. If a role addition on an HR-related group doesn't seem to be taking effect, this is worth checking.
- It can obscure the "Changed by" field on role-related audit trails, since the update is performed by a background job rather than attributed directly to your session. If accurate attribution matters for compliance, keep this in mind.
Optional Fix Script for Role Removal
If you need to automate the removal rather than do it through the UI, you can delete the relationship record directly from sys_group_has_role:
var groupName = 'Your_Group_Name';
var roleName = 'role_a';
var group = new GlideRecord('sys_user_group');
group.addQuery('name', groupName);
group.query();
if (group.next()) {
var role = new GlideRecord('sys_user_role');
role.addQuery('name', roleName);
role.query();
if (role.next()) {
var groupRole = new GlideRecord('sys_group_has_role');
groupRole.addQuery('group', group.sys_id);
groupRole.addQuery('role', role.sys_id);
groupRole.query();
while (groupRole.next()) {
groupRole.deleteRecord();
gs.info('Removed role ' + roleName + ' from group ' + groupName);
}
} else {
gs.info('Role not found: ' + roleName);
}
} else {
gs.info('Group not found: ' + groupName);
}
This removes the group-role relationship directly, which is what actually drives the downstream recalculation — same effect as removing it through the UI, just scriptable. With the async property enabled, the recalculation this triggers still runs as a background job rather than inline with the script.
What Happens After Removing the Role
Once the group-role relationship is removed, ServiceNow recalculates role inheritance for affected users in the background (assuming the async property is enabled). If a user doesn't inherit that role through any other group or direct assignment, it's removed from their user record once the recalculation completes.
Tracking Who Changed What
If you're doing access cleanup like this in an environment where auditability matters, it's worth knowing about glide.role_management.v2.audit_roles. When enabled, it logs role changes to the sys_audit_role table — useful for showing exactly what changed and when during a cleanup like this. It isn't available out of the box; you'd need to create the property and set it to true if you want this tracking.
Best Practices for Large Role Changes
- Check whether
glide.ui.schedule_slushbucket_save_for_group_rolesis already enabled before assuming you need to turn it on. - Test role changes in a lower environment first, especially for groups with HR-scoped roles given the known interaction above.
- Monitor the background job queue when performing changes on large groups — don't assume completion just because the UI stopped showing a spinner.
- Avoid large role changes during peak platform usage, since background jobs still compete for system resources.
- If attribution matters for compliance, consider enabling role change auditing before making the change, not after.
Conclusion
Removing roles from large groups can time out if ServiceNow tries to process every user's role recalculation within a single request. Enabling asynchronous group role updates — checking first whether it's already on — moves that work to a background job and avoids the timeout, though it's worth knowing its edge cases around parent-field changes, HR-scoped roles, and audit attribution before relying on it for a sensitive cleanup.

No comments:
Post a Comment