ACL Misconceptions That Hurt Performance

What the Advanced flag really does and why heavy ACL scripts get expensive

ACLs are easy to treat as a pure security feature and forget that they also sit on a hot path.

When an instance loads a form, renders a list, or reads fields through server-side code, ACL evaluation can happen many times. That is why small misunderstandings in ACL design turn into both security confusion and avoidable performance cost.

These are the misconceptions I see most often.

1. The Advanced flag does not disable the ACL script

This is probably the most common misunderstanding.

On an ACL record, the Advanced flag controls whether the script field is shown in the form. It does not decide whether existing script logic is executed.

That means this situation is possible:

  • an ACL already has script logic saved
  • someone later clears the Advanced flag
  • the script field is hidden
  • the script still participates in the ACL evaluation

So if behavior feels inconsistent, do not assume “Advanced = false” means “no script is running.” It may simply mean the script is no longer visible in that form layout.

2. ACLs are not automatically slow, but ACL scripts can become expensive

People sometimes say “ACLs are slow” as if the record itself is the problem.

The issue is usually not the existence of an ACL. The issue is what the ACL has to do every time access is checked.

ACL checks can occur:

  • when a list loads many rows
  • when a form renders many fields
  • when code reads records through secure APIs
  • when related data causes repeated field-level checks

If an ACL script performs extra queries, builds large objects, or logs aggressively, that work can be repeated far more often than expected.

3. One expensive ACL script can be multiplied across rows and fields

This is where the performance impact becomes visible.

A script that feels cheap for one record may become expensive when:

  • a list shows dozens or hundreds of rows
  • the same table has several field ACLs
  • the script performs another database query for each evaluation

Bad pattern:

var task = new GlideRecord("incident_task");
task.addQuery("incident", current.sys_id);
task.addActiveQuery();
task.query();

answer = task.hasNext();

That may look harmless, but if it runs repeatedly during access evaluation, you have just added extra database work to the security layer.

ACL scripts should be treated like code that may run frequently, not like a one-time business rule.

4. Prefer roles and conditions before you reach for script

The fastest ACL script is the one you do not need.

If access can be expressed with roles, use roles. If it can be expressed with a condition, use a condition. Script should be the fallback for logic that cannot be modeled cleanly any other way.

This is not only about performance. It is also about readability. A role-based ACL is easier to audit than a script that mixes access rules, queries, and edge cases.

A good mental order is:

  1. Can a role decide this?
  2. Can a simple condition decide this?
  3. Only then, do I actually need script?

5. Passing one ACL does not mean the user will get access

Another common mistake is debugging one ACL in isolation and assuming that success there should grant access overall.

Access decisions can involve table-level and field-level ACLs, and multiple rules may participate in the final result depending on the operation and data being accessed.

So when a user still cannot read a record, do not stop at “this ACL returned true.” Keep checking the rest of the applicable security rules.

This is also why performance tuning has to look at the whole set of ACLs on a table, not only the one script that first caught your attention.

6. Admin override is not a universal escape hatch

It is common to assume that checking Admin overrides means administrators will always pass.

In practice, ACL behavior can still be affected by the broader ACL set and instance configuration. If admin access behaves unexpectedly, inspect the full security picture instead of assuming the checkbox alone guarantees the outcome.

That matters for performance too: teams sometimes add more custom ACL logic while debugging admin behavior, when the real problem is a misunderstanding of how the existing rules combine.

7. Keep ACL scripts narrow and predictable

If you do need script, keep it cheap.

Good ACL script habits:

  • use data already available on current when possible
  • avoid extra GlideRecord queries inside the ACL
  • avoid loops over large related datasets
  • avoid verbose logging in normal execution
  • return a simple boolean answer

Reasonable pattern:

answer = gs.hasRole("itil") ||
  current.getValue("caller_id") == gs.getUserID();

This kind of check is short, obvious, and does not add extra database reads.

8. Field ACLs deserve extra caution

Table ACLs are important, but field ACLs are often where performance surprises show up.

A single scripted field ACL can be evaluated repeatedly across many fields or rows. If that script performs additional server work, the cost multiplies quickly.

So if a page feels slow after security changes, inspect scripted field ACLs first. They are a common place for hidden repetition.

9. Debug security with the right question

When an ACL issue shows up, ask two separate questions:

  1. Is the access decision correct?
  2. Is the way we compute that decision efficient?

Those are not the same problem.

An ACL can be logically correct and still be too expensive because it performs unnecessary lookups. It can also be fast and still be wrong because the team misunderstood Advanced, Admin overrides, or the number of ACLs participating in the check.

Keeping those two questions separate usually leads to cleaner fixes.

A practical default

When designing ACLs, this is the bias I try to keep:

  • Prefer roles over script.
  • Prefer conditions over script when the logic is simple.
  • If script is necessary, keep it short and free of extra queries.
  • Be especially careful with scripted field ACLs.
  • Never assume the Advanced flag disables existing script logic.

Final thought

ACLs are part of normal platform behavior, so their cost is easy to underestimate.

Most ACL performance problems do not come from security itself. They come from heavy script logic placed in a layer that may run again and again across records, fields, and requests.

If the rule is simple, keep it simple. If the rule must be scripted, write it as if it will run a lot, because it probably will.

comments powered by Disqus

Related