Architecture
Your enterprise customer has 5 ServiceNow production instances (each ~10k users) serving different business…
The question
function onInsert(current, previous) { var gr = new GlideRecord('incident'); gr.addQuery('priority', '1'); gr.query(); while(gr.next()) { // process... } } Rewrite this as an efficient, domain/multi-tenant aware solution using GlideAggregate and async processing.What This Question Really Tests
In a multi-instance setup like this (5 instances, 10k users each), symptoms point to resource contention, poor isolation, and inefficient code. Root cause diagnosis starts with structured triage: (1) Review Instance Scan/HealthScan for CPU/memory baselines; (2) Analyze Transaction Logs & Slow Query logs via Performance Analytics for top consumers (e.g., BRs, workflows); (3) Use System Diagnostics > Slow Queries to pinpoint unindexed scans; (4) Check domain separation config via Domain Management for leaks; (5) Correlate with MID Server logs for discovery/CMDB issues. Avoid jumping to multi-instance—first rule out code/config fixes, as cloning overhead suggests underutilized capacity.
The Solution
Diagnosis confirms the global BR as primary culprit—full table scans on insert amplify across instances. Solution: Replace with GlideAggregate for aggregation, domain filtering, and event-driven async via gs.eventQueue() for decoupling. This sharply reduces the synchronous load and respects multi-tenancy.
function onInsert(current, previous) {
// Domain-aware filter for multi-instance safety
var domain = gs.getUser().getDomainID();
var ga = new GlideAggregate('incident');
ga.addQuery('priority', '1');
ga.addQuery('sys_domain', domain); // Tenant isolation
ga.addAggregate('COUNT');
ga.query();
if (ga.next()) {
var highPriorityCount = ga.getAggregate('COUNT');
// Async event for processing, avoids sync blocking
gs.eventQueue('inc.high.priority.threshold', current, highPriorityCount, domain);
}
}Handle the event in a Script Action or Script Include: process the batch via a scheduled job and cache repeated lookups in script variables for the duration of the run (there is no external cache like Redis available on the platform).
Senior Considerations
- 3 Options with Trade-offs: Option 1: Optimize single sub-prod instance (fix code, add indexes, Flow Designer async)—cheapest/fastest, but shared DB risks cascades (good answer stops here). Option 2: Domain Separation (logical isolation via sys_domain_path)—scales to 100+ tenants, zero data migration, but complex ACLs/debugging; ideal if <20 tenants. Option 3: Multi-Instance (recommended)—physical isolation, per-tenant scaling/upgrade cadence, but 3x infra cost, integration via Integration Hub, data sync via Transform Maps. Choose #3 for regulated units (Legal/Finance) needing strict isolation vs. perf.
- Production Migration: Pilot HR instance to new pod (A/B test 2wks), use Update Sets for config, RITM-driven cutover with rollback (clone-back), monitor via AIOps. Edge case: cross-release upgrade drift—standardize via Instance Clone selective.
- What Separates Good vs Great: A good answer lists domain separation vs multi-instance; a great one explains where domain separation stops scaling in practice, discusses failure modes (e.g., cross-domain queries via Database Views), proposes monitoring (Event Management rules), and justifies the choice via total cost of ownership at large user counts.
- Why Async + Aggregate: Sync BRs block transactions (5s+ latency); aggregate avoids N+1, events decouple for elastic queues—core to ServiceNow's multi-tenant DNA. Test both patterns on a PDI with realistic record volumes and compare.