Anti-pattern 1: Querying without a limit on large tables
// Bad - loads ALL incidents into memory
var gr = new GlideRecord('incident');
gr.query();
while (gr.next()) { ... }
// Good - always set a limit when you don't need everything
var gr = new GlideRecord('incident');
gr.addEncodedQuery('active=true^state=1');
gr.setLimit(100);
gr.query();
Anti-pattern 2: Counting with a loop
// Bad
var count = 0;
var gr = new GlideRecord('incident');
gr.query();
while (gr.next()) { count++; }
// Good - pushes count to database level
var ga = new GlideAggregate('incident');
ga.addEncodedQuery('active=true');
ga.addAggregate('COUNT');
ga.query();
if (ga.next()) { var count = ga.getAggregate('COUNT'); }
Anti-pattern 3: Loading unnecessary fields
By default GlideRecord loads all columns. Use chooseWindow() or addFieldToSelect() when you only need specific fields on large tables:
var gr = new GlideRecord('cmdb_ci');
gr.addEncodedQuery('operational_status=1');
gr.setWorkflow(false); // Don't fire Business Rules
gr.query();
while (gr.next()) {
gs.log(gr.getValue('name') + ' - ' + gr.getValue('ip_address'));
}
Anti-pattern 4: GlideRecord inside a loop
// Bad - N+1 query problem
while (gr.next()) {
var userGr = new GlideRecord('sys_user');
userGr.get(gr.assigned_to); // Separate DB hit per record
gs.log(userGr.name);
}
// Good - use dot-walking or getDisplayValue()
while (gr.next()) {
gs.log(gr.assigned_to.getDisplayValue()); // One query, display value resolved
}
Anti-pattern 5: Calling update() in a Before Business Rule
In a Before rule, setting values on current and letting the platform save them is free. Calling current.update() inside a Before rule causes an extra database write and can trigger additional Business Rules — potentially causing a loop.
setWorkflow(false) and autoSysFields(false)
gr.setWorkflow(false); // Don't run Business Rules on this save
gr.autoSysFields(false); // Don't auto-update sys_updated_on etc.
Use both when doing maintenance updates in Scheduled Jobs where you don't want side effects.