Best Practice? Enforcing Max Member Count on Resource Assignment Groups (sys_user_group)

dpattersonryder
Tera Contributor

Hi everyone,

I'm working on a use case where we need to enforce a strict maximum number of users assigned to any given Resource Assignment Group in SPM.

Business Logic:

Limit group membership to 100 users.

Applies only to groups that have the pps_resource role assigned.

Enforcement must apply whether members are added individually or via the "Edit Members" related list UI.

Solution Attempted:

I wrote a Before Insert Business Rule on sys_user_grmember (Group Members table).

I also wrote a Before Update Business Rule on sys_user_group to catch the Edit Members use case.

My logic dynamically checks for the pps_resource role on the group and evaluates member count using GlideAggregate.

The BR works fine under certain test conditions (API inserts, normal updates, etc).

The challenge:

When I try to test updates using Background Scripts with GlideRecord.update(), my Business Rule doesn’t appear to fire.

The record updates as expected.

My logging (gs.info()) inside the BR never outputs.

Member counts evaluate fine when tested separately.

The BR does fire properly when using the UI directly (Edit Members).

My questions for the community:

Is there a better way to enforce a membership cap directly on sys_user_group?

Is this the correct table to enforce against for the "Edit Members" list edits?

Is there a more reliable server-side way to fully simulate this update behavior (vs using background scripts)?

Any recommendations on platform-safe ways to enforce member cardinality across UI, API, imports, etc?

Environment:

ServiceNow Xanadu Build

SPM Resource Assignment in use

Global scope

I’d love to hear how others have handled similar "data integrity" constraints for cardinality enforcement inside ServiceNow, especially on these parent-child tables like groups and members.

Thanks in advance!

1 ACCEPTED SOLUTION

YaswanthKurre
Tera Guru

Hi @dpattersonryder ,

 

Answers to your questions:

1. Is there a better way to enforce a membership cap directly on sys_user_group?

  • No, not directly. The membership count is derived data from the sys_user_grmember table. You cannot enforce a cardinality constraint on the parent table (sys_user_group) without querying its child table (sys_user_grmember).

  • The sys_user_grmember table is the correct and necessary place to enforce this. All changes to group membership (individual additions, "Edit Members," imports, API calls) ultimately create or delete records in sys_user_grmember.

2. Is this the correct table to enforce against for the "Edit Members" list edits?

  • Yes, sys_user_grmember is absolutely the correct table. As explained, "Edit Members" triggers inserts and deletes on sys_user_grmember. Your Before Insert and Before Delete Business Rules on this table are precisely where you need to implement the logic.

3. Is there a more reliable server-side way to fully simulate this update behavior (vs using background scripts)?

  • To simulate "Edit Members" in a background script, you would need to write scripts that perform GlideRecord.insert() and GlideRecord.delete() operations directly on the sys_user_grmember table, mirroring what the UI does.

  • Your existing gs.info() statements will only show if the BR actually fires.

 

4. Any recommendations on platform-safe ways to enforce member cardinality across UI, API, imports, etc.?

  • The most robust and platform-safe way is to use a Before Insert Business Rule on sys_user_grmember.

Please mark this as helpful and correct if this helps you.

 

Thanks,

Yaswanth

View solution in original post

3 REPLIES 3

YaswanthKurre
Tera Guru

Hi @dpattersonryder ,

 

Answers to your questions:

1. Is there a better way to enforce a membership cap directly on sys_user_group?

  • No, not directly. The membership count is derived data from the sys_user_grmember table. You cannot enforce a cardinality constraint on the parent table (sys_user_group) without querying its child table (sys_user_grmember).

  • The sys_user_grmember table is the correct and necessary place to enforce this. All changes to group membership (individual additions, "Edit Members," imports, API calls) ultimately create or delete records in sys_user_grmember.

2. Is this the correct table to enforce against for the "Edit Members" list edits?

  • Yes, sys_user_grmember is absolutely the correct table. As explained, "Edit Members" triggers inserts and deletes on sys_user_grmember. Your Before Insert and Before Delete Business Rules on this table are precisely where you need to implement the logic.

3. Is there a more reliable server-side way to fully simulate this update behavior (vs using background scripts)?

  • To simulate "Edit Members" in a background script, you would need to write scripts that perform GlideRecord.insert() and GlideRecord.delete() operations directly on the sys_user_grmember table, mirroring what the UI does.

  • Your existing gs.info() statements will only show if the BR actually fires.

 

4. Any recommendations on platform-safe ways to enforce member cardinality across UI, API, imports, etc.?

  • The most robust and platform-safe way is to use a Before Insert Business Rule on sys_user_grmember.

Please mark this as helpful and correct if this helps you.

 

Thanks,

Yaswanth

Maik Skoddow
Tera Patron
Tera Patron

Hi @dpattersonryder 

basically you are on the right path, however you only need a BR on the sys_user_grmember table for the insert case. Only on that table counting members makes sense and also only that table is incorporated for the "Edit members" use case.

Why it is not working in some cases for you, depends on the implementation. However, you have not provided more details and therefore we cannot help you any further.

Maik

dpattersonryder
Tera Contributor

Guys it worked, Thank you for your great responses.