A reference qualifier looks innocent in the dictionary editor: one line of script or one encoded query. In production it executes on every form load, every list edit, and every catalog item render. A 200ms qualifier on a heavily used field becomes 200,000ms per day at modest volume. Most performance complaints about “slow forms” trace back to two or three bad qualifiers.
Find the offenders
Query sys_dictionary where reference_qual_condition is not empty or use_reference_qualifier equals advanced. Cross-reference with the most-loaded forms from the Transaction Log. Anything in the top 50 forms with a scripted qualifier is a candidate for review. Add gs.log timing wrappers temporarily and you will quickly see which ones exceed 100ms.
Prefer simple over advanced
The simple qualifier type compiles to an indexed encoded query. The advanced type runs a server-side script that often re-queries data already cached in the form. If you can express the constraint as active=true^company=javascript:gs.getUser().getCompanyID(), do it that way. Reserve scripts for cases where the constraint genuinely depends on multiple unrelated tables.
Cache user context outside the qualifier
A common anti-pattern looks like this:
var grUser = new GlideRecord('sys_user');
grUser.get(gs.getUserID());
return 'department=' + grUser.department;
That fires a database round-trip every time the qualifier runs. Use gs.getUser().getRecord().getValue('department') instead, which hits the session cache. On a busy form this single change can cut 50 to 100ms.
Avoid GlideRecord loops in qualifiers
If a qualifier walks records to build an IN clause, the result set grows unbounded and the encoded query becomes a multi-kilobyte string. Rewrite as a join condition or move the logic to a database view. Anything returning more than a few hundred sys_ids in the IN clause will degrade as data grows.
Watch for client-side amplification
Reference qualifiers also fire from List v3 inline edits and from reference fields inside slushbuckets. A qualifier that runs once per form load may run once per row when a user edits a list. Test with a 50-row list, not a single record, before declaring something fast.
Measure with the Slow Query log, not gut feel
Enable the Slow Query log with a 100ms threshold and let it run for 24 hours. Filter the results by transactions originating from getRefRecords or referenceQualifier calls. The top 10 by total time are your full backlog. Fix those and your form-load complaints typically drop by half.
Document the qualifier next to the field
Reference qualifiers are notoriously undocumented. Add a Hint on the dictionary entry explaining what the qualifier does and why. The next engineer to touch the field will not have to reverse-engineer the intent from a one-liner.
What to do this week: enable the Slow Query log, find your three worst reference qualifiers, and rewrite them as simple encoded queries where possible.