Group membership queries trip up developers because ServiceNow provides multiple APIs that behave differently under domain separation and performance constraints. The sys_user_grmember table is the authoritative source β it contains the actual membership records with proper domain handling and ACL enforcement. Developers often reach for GlideGroupChoice or gs.getUser().isMemberOf() first, but these have caching issues and don't work reliably in all execution contexts.
When to use this
- In Business Rules, Script Includes, and Scheduled Jobs where you need definitive group membership
- When domain separation is enabled and you need domain-aware results
- For checking membership of users other than the current session user
- When you need to retrieve all groups for a user and process them programmatically
When NOT to use this
- In client scripts β use GlideAjax to call this server-side function instead
- For simple current user checks in ACL scripts β use
gs.getUser().isMemberOf()which is cached and faster - Inside loops over large record sets β cache the group membership results instead
- For UI Policy conditions β use role-based conditions or reference qualifiers instead
Key behaviors and gotchas
- The
group.namedot-walk is indexed and performs better than joining tables manually - Always use
setLimit(1)when you only need to check existence β stops query after first match - Group membership respects domain separation β users only see groups in their domain or global
- The
userfield stores sys_id values, not user names β never query by user_name here - Group names are case-sensitive and must match exactly β trim and validate input
GlideGroupChoice only works reliably for the current user and can return stale cached results. In Scheduled Jobs and Business Rules triggered by system users, it may return empty or incorrect results. Always query sys_user_grmember directly when the context isn't a normal user session.