Skip to Content
  1. Home
  2. /
  3. Blog
  4. /
  5. Complete Guide to ServiceNow Performance Monitoring and Optimization
Monday, March 2, 2026

Complete Guide to ServiceNow Performance Monitoring and Optimization

Complete Guide to ServiceNow Performance Monitoring and Optimization

Performance monitoring is critical for maintaining a healthy ServiceNow instance. Slow performance can impact user productivity, SLA compliance, and overall business operations. This comprehensive guide covers ServiceNow's built-in monitoring tools, optimization strategies, and best practices for keeping your instance running at peak performance.

Understanding ServiceNow Performance Metrics

Key Performance Indicators (KPIs)

Response Time Metrics:

  • Page load times (target: <3 seconds)
  • API response times (target: <1 second)
  • Database query execution times
  • Script execution duration

Resource Utilization:

  • CPU usage patterns
  • Memory consumption
  • Database connection pools
  • Thread pool utilization

User Experience Metrics:

  • Session timeouts
  • Concurrent user load
  • Transaction success rates
  • Error frequencies

Built-in Performance Monitoring Tools

1. Performance Analytics Dashboard

Navigate to System Definition > Performance Analytics > Dashboards to access comprehensive performance insights.

Key Widgets to Monitor:

  • Response Time Trends
  • Database Performance
  • Slow Transactions
  • Error Rate Analysis
JavaScript
// Script to create custom performance metric
var gr = new GlideRecord('sys_performance');
gr.addQuery('transaction', 'incident.do');
gr.addQuery('sys_created_on', '>', gs.daysAgoStart(7));
gr.orderByDesc('response_time');
gr.setLimit(20);
gr.query();

while (gr.next()) {
    gs.info('Slow transaction: ' + gr.url + ' - ' + gr.response_time + 'ms');
}

2. Stats Module

Access System Diagnostics > Stats for real-time system metrics.

Critical Stats to Monitor:

  • glide.db.max_connections.used
  • glide.threads.available
  • glide.cache.size
  • glide.memory.heap.used

3. System Logs and Metrics

Application Log Analysis:

JavaScript
// Query for performance-related log entries
var gr = new GlideRecord('syslog');
gr.addQuery('level', 'error');
gr.addQuery('source', 'CONTAINS', 'performance');
gr.addQuery('sys_created_on', '>', gs.daysAgoStart(1));
gr.orderByDesc('sys_created_on');
gr.query();

while (gr.next()) {
    gs.info('Performance Error: ' + gr.message);
}

Database Performance Optimization

Query Optimization Strategies

1. Index Analysis and Creation:

JavaScript
// Find tables without proper indexing
var gr = new GlideRecord('sys_db_table');
gr.query();

while (gr.next()) {
    var indexCount = new GlideRecord('sys_db_index');
    indexCount.addQuery('table', gr.sys_id);
    indexCount.query();
    
    if (indexCount.getRowCount() < 2) {
        gs.info('Table may need indexing: ' + gr.name);
    }
}

2. Slow Query Detection:

Enable slow query logging in your instance properties:

  • glide.db.debug.log.query.threshold = 5000 (log queries > 5 seconds)
  • glide.db.query.timeout = 30 (timeout after 30 seconds)

Database Maintenance Best Practices

Regular Cleanup Procedures:

  • Archive old records using cleanup jobs
  • Monitor table growth trends
  • Implement retention policies
  • Regular database statistics updates
JavaScript
// Example: Auto-cleanup script for old sys_email records
var cleanup = new GlideRecord('sys_email');
cleanup.addQuery('sys_created_on', '<', gs.daysAgoEnd(90));
cleanup.addQuery('state', 'sent');
cleanup.setLimit(1000);
cleanup.query();

var deleteCount = 0;
while (cleanup.next()) {
    cleanup.deleteRecord();
    deleteCount++;
}

gs.info('Cleaned up ' + deleteCount + ' old email records');

Script Performance Optimization

Business Rules Optimization

Performance Best Practices:

  1. Use appropriate timing: Use 'before' rules for validation, 'after' for notifications
  2. Minimize database calls: Batch operations when possible
  3. Avoid unnecessary queries: Use current object properties instead of new queries

Optimized Business Rule Example:

JavaScript
// BAD: Multiple database calls
function onChange(control, oldValue, newValue, isLoading) {
    if (current.state == '6') {
        var user = new GlideRecord('sys_user');
        user.get(current.assigned_to);
        
        var manager = new GlideRecord('sys_user');
        manager.get(user.manager);
        
        // Send notification
    }
}

// GOOD: Single optimized query
function onChange(control, oldValue, newValue, isLoading) {
    if (current.state == '6') {
        var userGR = new GlideRecord('sys_user');
        userGR.addQuery('sys_id', current.assigned_to);
        userGR.query();
        
        if (userGR.next()) {
            var managerEmail = userGR.manager.getDisplayValue();
            // Process with manager info
        }
    }
}

Script Include Optimization

Caching Strategies:

JavaScript
// Implement caching for frequently accessed data
var CacheUtils = Class.create();
CacheUtils.prototype = {
    initialize: function() {
        this.cache = {};
        this.cacheTimeout = 300000; // 5 minutes
    },
    
    getUserRoles: function(userSysId) {
        var cacheKey = 'user_roles_' + userSysId;
        var cached = this.cache[cacheKey];
        
        if (cached && (gs.now().getTime() - cached.timestamp) < this.cacheTimeout) {
            return cached.data;
        }
        
        // Fetch fresh data
        var roles = [];
        var gr = new GlideRecord('sys_user_has_role');
        gr.addQuery('user', userSysId);
        gr.query();
        
        while (gr.next()) {
            roles.push(gr.role.name.toString());
        }
        
        // Cache the results
        this.cache[cacheKey] = {
            data: roles,
            timestamp: gs.now().getTime()
        };
        
        return roles;
    },
    
    type: 'CacheUtils'
};

Memory Management and Resource Optimization

Session Management

Monitor Session Health:

JavaScript
// Script to identify long-running sessions
var sessions = new GlideRecord('sys_user_session');
sessions.addQuery('sys_created_on', '<', gs.daysAgoStart(1));
sessions.addQuery('logged_out', 'false');
sessions.query();

while (sessions.next()) {
    gs.info('Long session: User=' + sessions.user.name + 
            ', Duration=' + sessions.sys_created_on.dateNumericValue());
}

Cache Optimization

Configure Instance Caching:

  • glide.cache.default.size = 2048
  • glide.cache.max_size = 4096
  • glide.ui.cache.list_edit.lifetime = 1800

Memory Leak Prevention

Common Memory Leak Patterns to Avoid:

JavaScript
// BAD: Memory leak in scheduled job
function executeMyJob() {
    var largeArray = [];
    var gr = new GlideRecord('large_table');
    gr.query();
    
    while (gr.next()) {
        largeArray.push(gr); // Keeping references to GlideRecord objects
    }
    
    // Process array... but references remain in memory
}

// GOOD: Process records incrementally
function executeMyJob() {
    var gr = new GlideRecord('large_table');
    gr.query();
    
    while (gr.next()) {
        // Process individual record
        processRecord(gr.getValue('field1'), gr.getValue('field2'));
        // GlideRecord automatically dereferenced each iteration
    }
}

Monitoring and Alerting Setup

Custom Performance Monitors

Create Performance Monitoring Scripts:

JavaScript
// Scheduled Script: Performance Health Check
var PerformanceMonitor = Class.create();
PerformanceMonitor.prototype = {
    initialize: function() {
        this.thresholds = {
            dbConnections: 80,  // Percentage of max connections
            heapMemory: 85,     // Percentage of heap
            responseTime: 3000  // Milliseconds
        };
    },
    
    checkDatabaseConnections: function() {
        var used = parseInt(gs.getProperty('glide.db.max_connections.used', '0'));
        var max = parseInt(gs.getProperty('glide.db.max_connections', '20'));
        var percentage = (used / max) * 100;
        
        if (percentage > this.thresholds.dbConnections) {
            this.createAlert('High database connection usage: ' + percentage + '%');
        }
        
        return percentage;
    },
    
    checkMemoryUsage: function() {
        var heapUsed = parseInt(gs.getProperty('glide.memory.heap.used', '0'));
        var heapMax = parseInt(gs.getProperty('glide.memory.heap.max', '1'));
        var percentage = (heapUsed / heapMax) * 100;
        
        if (percentage > this.thresholds.heapMemory) {
            this.createAlert('High memory usage: ' + percentage + '%');
        }
        
        return percentage;
    },
    
    createAlert: function(message) {
        var alert = new GlideRecord('sys_email');
        alert.initialize();
        alert.recipients = 'admin@company.com';
        alert.subject = 'ServiceNow Performance Alert';
        alert.body = message + '\n\nInstance: ' + gs.getProperty('instance_name');
        alert.insert();
    },
    
    type: 'PerformanceMonitor'
};

// Execute monitoring
var monitor = new PerformanceMonitor();
monitor.checkDatabaseConnections();
monitor.checkMemoryUsage();

Performance Dashboard Creation

Build Custom Performance Widgets:

JavaScript
// Widget Script for Performance Dashboard
(function() {
    // Fetch performance data
    var data = {};
    
    // Response time data
    var responseGR = new GlideRecord('sys_performance');
    responseGR.addQuery('sys_created_on', '>', gs.daysAgoStart(7));
    responseGR.orderBy('sys_created_on');
    responseGR.query();
    
    data.responseTimes = [];
    while (responseGR.next()) {
        data.responseTimes.push({
            timestamp: responseGR.sys_created_on.toString(),
            responseTime: responseGR.response_time.toString(),
            url: responseGR.url.toString()
        });
    }
    
    // Memory usage data
    data.memoryStats = {
        heapUsed: gs.getProperty('glide.memory.heap.used'),
        heapMax: gs.getProperty('glide.memory.heap.max'),
        connections: gs.getProperty('glide.db.max_connections.used')
    };
    
    return data;
})();

Performance Testing and Benchmarking

Load Testing Strategies

Automated Performance Tests:

JavaScript
// Performance test script for critical transactions
var PerformanceTest = Class.create();
PerformanceTest.prototype = {
    initialize: function() {
        this.results = [];
    },
    
    testIncidentCreation: function() {
        var startTime = new Date().getTime();
        
        // Create test incident
        var incident = new GlideRecord('incident');
        incident.initialize();
        incident.short_description = 'Performance test incident';
        incident.description = 'Created for performance testing';
        incident.urgency = '3';
        incident.impact = '3';
        var incidentId = incident.insert();
        
        var endTime = new Date().getTime();
        var duration = endTime - startTime;
        
        this.results.push({
            transaction: 'incident_creation',
            duration: duration,
            timestamp: new Date()
        });
        
        // Cleanup
        if (incidentId) {
            incident.get(incidentId);
            incident.deleteRecord();
        }
        
        return duration;
    },
    
    generateReport: function() {
        var avgDuration = 0;
        for (var i = 0; i < this.results.length; i++) {
            avgDuration += this.results[i].duration;
        }
        avgDuration = avgDuration / this.results.length;
        
        gs.info('Performance Test Results:');
        gs.info('Average Duration: ' + avgDuration + 'ms');
        gs.info('Total Tests: ' + this.results.length);
    },
    
    type: 'PerformanceTest'
};

Best Practices Summary

Daily Monitoring Checklist

  1. Review Performance Dashboard: Check response times and error rates
  2. Monitor Resource Usage: CPU, memory, database connections
  3. Check Slow Queries: Review database performance logs
  4. Validate Scheduled Jobs: Ensure jobs complete within expected timeframes
  5. User Experience Metrics: Monitor support ticket trends

Weekly Deep Dive

  1. Performance Trend Analysis: Week-over-week performance comparison
  2. Capacity Planning: Project resource needs based on growth trends
  3. Script Performance Review: Identify optimization opportunities
  4. Cache Hit Rate Analysis: Optimize caching strategies
  5. System Health Report: Comprehensive instance health assessment

Monthly Optimization

  1. Database Maintenance: Index optimization and cleanup
  2. Performance Baseline Updates: Adjust thresholds based on new patterns
  3. Capacity Scaling Review: Plan infrastructure adjustments
  4. Business Rule Audit: Remove unnecessary or redundant rules
  5. Performance Policy Updates: Refine monitoring and alerting rules

Conclusion

Effective ServiceNow performance monitoring requires a combination of proactive monitoring, regular optimization, and strategic planning. By implementing these monitoring strategies and optimization techniques, you can maintain optimal performance even as your instance grows and evolves.

Remember that performance optimization is an ongoing process. Regular monitoring, timely interventions, and continuous improvement are key to maintaining a high-performing ServiceNow instance that supports your organization's business objectives.

Start with the basic monitoring tools, implement the optimization strategies that align with your current challenges, and gradually build a comprehensive performance management framework that ensures your ServiceNow instance delivers consistent, reliable performance for all users.

Was this article helpful?