The pattern is everywhere in legacy code: var gr = new GlideRecord('incident'); gr.query(); return gr.getRowCount();. It works, it returns the right number, and it slowly destroys instance performance. GlideAggregate is the right tool, and the difference is not subtle.
What actually happens with getRowCount
gr.query() issues SELECT * FROM incident WHERE .... The database materializes every row. The application server hydrates them into Java objects. Then getRowCount returns the size of the result set. On a table with a million records, a wide-open query allocates roughly 400MB of heap before you ever read a value.
new GlideAggregate('incident') with addAggregate('COUNT') issues SELECT COUNT(*) FROM incident WHERE .... The database returns one number. No hydration, no heap pressure, no transaction log noise.
Measured difference on a 2M-row table
In a benchmark on a paid sub-prod instance with a 2 million row incident table:
GlideRecord+getRowCountoveractive=true: 4.2 seconds, 380MB heap allocationGlideAggregate+addAggregate('COUNT')same filter: 110ms, negligible heap
The advantage shrinks for narrow filters that return few rows but never reverses. There is no scenario where GlideRecord-for-counting wins.
The right pattern
var ga = new GlideAggregate('incident');
ga.addQuery('active', true);
ga.addQuery('priority', '1');
ga.addAggregate('COUNT');
ga.query();
var count = 0;
if (ga.next()) {
count = parseInt(ga.getAggregate('COUNT'), 10);
}
Wrap that in a helper if you call it often. Make sure the helper returns an integer; getAggregate returns a string and silent string-math bugs are common.
Group counts are even more lopsided
If you need counts grouped by category or assignment group, the GlideRecord approach forces you to iterate every record and tally in JavaScript. GlideAggregate with groupBy('assignment_group') returns the grouped counts in a single query. The performance gap on grouped operations is often 100x or more.
Watch for ACL evaluation
GlideAggregate respects ACLs by default, which can change the count compared to a raw SQL count. If you need the unfiltered total for a system metric, use setStrategy('count_unique') or escalate to a fix script with explicit setWorkflow(false) only where appropriate. Never disable ACLs in user-facing code.
Indexes still matter
GlideAggregate is fast because the database does the work, which means it is only as fast as your indexes. Counts filtered on unindexed columns degrade just like any other query. Check the slow query log for aggregate queries exceeding 500ms and add indexes on the filter columns.
Find the legacy pattern in your codebase
Run an Instance Scan check for the regex getRowCount\s*\( across sys_script, sys_script_include, and sys_ui_action. Any hit is a refactor candidate. Most instances have dozens; a few have hundreds.
What to do this week: run the regex scan, pick the top five hits by execution frequency, and rewrite them as GlideAggregate.