Record-level ACLs let you filter what data users can see within a table based on field values, relationships, or complex business logic. You'll build one with a condition script and understand how to avoid the performance pitfalls that can cripple your instance.
Why record-level ACLs exist
Before record-level ACLs, teams had two bad choices for data security: give users access to entire tables (too permissive) or create duplicate tables with different permissions (maintenance nightmare). Platform admins and developers needed a way to show users only the records they should see — their own incidents, their department's requests, or clients they manage. Without this capability, you end up either over-exposing sensitive data or building complex workarounds that break when business rules change.
How record-level ACLs work
A record-level ACL runs a condition script against every single record when ServiceNow builds a query result. The script has access to the 'current' object (the record being evaluated) and can check field values, traverse references, or call functions. If the condition returns true, the user sees the record. If false, ServiceNow filters it out. The critical thing to understand: this happens per-record, not per-query. A list view with 1000 records means your condition script runs 1000 times. Start with simple field comparisons, then add complexity only when necessary.
Optimizing for production use
The difference between a basic record ACL and a production-ready one is performance optimization. Production ACLs minimize database queries (never query inside the condition), cache expensive lookups, and use indexed fields whenever possible. You'll also want to monitor query performance after deployment and consider whether you need record-level filtering on high-volume tables at all — sometimes role-based table access or UI policies are better choices.
Before you start
- •security_admin role or admin role
- •Target table exists and contains test records
Sourdough: ServiceNow Monitoring and Analytics
A Chrome extension for ServiceNow Admins and Developers with essential tools, analytics, graphs and monitoring features.
Free to install. Pro $5/month after a 14-day no-card trial.
Pro requires the ServiceNow admin role. Upgrade inside the extension.
Step by step
Navigate to Access Control List
Go to System Security > Access Control (ACL) > Access Control List. You'll create the record-level rule here, separate from any table-level ACLs that might already exist.
Filter the list by your target table first to see what ACLs already exist — conflicting rules cause confusing behavior.
Create new ACL record
Click New to create a new ACL. Set Type to 'record', then select your target table in the Name field. Leave Operation as 'read' — that's what controls visibility. Set Active to true.
Don't set the Field value — that's for field-level ACLs, not record-level.
Configure role requirements
In the Requires role field, select the role that should have conditional access to records. Users without this role won't see any records from this table. If you need multiple roles, create separate ACL records for each one.
Choose the most restrictive role that makes sense — you can always create additional ACLs for broader access.
Write the condition script
Check the Advanced checkbox to reveal the Condition field. Write your JavaScript condition using the 'current' object to reference the record being evaluated. For example: 'current.assigned_to == gs.getUserID()' to show only records assigned to the current user. The condition must return true or false.
Test your logic with gs.log() statements first — ACL debugging is painful once the rule is active.
Test with specific records
Before saving, mentally walk through 3-4 existing records and verify your condition logic. Check edge cases like empty fields or null references. Your condition script should handle these gracefully without throwing errors.
Use 'current.field_name.nil()' instead of '!current.field_name' to safely check for empty reference fields.
Save and verify behavior
Click Submit to save the ACL. Navigate to a list view of your target table while impersonating a user with the required role. Verify that only the expected records appear and that the filtering works correctly across different users.
Best practices
Never perform database queries inside record ACL conditions — they'll execute once per record and destroy performance on large tables.
Use indexed fields in your conditions whenever possible — filtering on non-indexed fields forces full table scans.
Test record ACLs with users who have thousands of records, not just a few test records — performance problems only show up at scale.
Consider whether you actually need record-level filtering — sometimes role-based table access or UI policies solve the problem more efficiently.
Monitor query execution times after deploying record ACLs, especially on high-traffic tables like incident and task.
Test Your Knowledge
Quick 3-question quiz — see how your ServiceNow skills stack up.
A list view on a table with millions of records is slow. Best fix?
Select an answer to continue