Access Control

Create a Record-Level ACL with Conditions

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
Chrome Extension

Sourdough: ServiceNow Monitoring and Analytics

A Chrome extension for ServiceNow Admins and Developers with essential tools, analytics, graphs and monitoring features.

Instance HealthGraphs & ChartsAPI HealthDeveloper ToolsQuick SearchInstance Switcher
Add to Chrome

Free to install. Pro $5/month after a 14-day no-card trial.
Pro requires the ServiceNow admin role. Upgrade inside the extension.

Overview
Tasks
CMDB
API
Metrics
Monitor
Internals
Instance:sourdoughdev·Version:Yokohama
Instance StateONLINE
System StatusFully Operational
Session Timeout90 minutes
Logged-In Sessions2 (20 active)
Build Nameyokohama-12-18-2024_p1
IP Address10.159.128.43
Instance HealthHealth Score: 90%
🔥 5dSourdough (Chrome Plugin)Dark Mode

Step by step

1

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.

TIP

Filter the list by your target table first to see what ACLs already exist — conflicting rules cause confusing behavior.

2

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.

TIP

Don't set the Field value — that's for field-level ACLs, not record-level.

3

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.

TIP

Choose the most restrictive role that makes sense — you can always create additional ACLs for broader access.

4

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.

TIP

Test your logic with gs.log() statements first — ACL debugging is painful once the rule is active.

5

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.

TIP

Use 'current.field_name.nil()' instead of '!current.field_name' to safely check for empty reference fields.

6

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.

Question 1 of 3Performance

A list view on a table with millions of records is slow. Best fix?

Select an answer to continue