ServiceNow Platform Performance Best Practices
Understand Your Performance Baseline
Before optimising, measure current performance. What is the baseline? Form load time, list load time, report generation time, API response time. Once measured, improvements can be validated.
Use browser developer tools to measure page load time. Use the slow query log to find expensive database queries. Monitor system metrics (CPU, memory, disk I/O). Create a baseline report: list the top 10 slowest pages, top 10 slowest reports, top 10 slowest API endpoints.
Target performance: set targets for forms, lists, reports and API responses, based on your users’ expectations and your data volume. These targets are achievable for well-designed systems; if performance falls short, investigate and fix.
Optimise Database Queries With Proper Indexing
Database performance is the foundation. If queries are slow, everything is slow. Slow queries usually mean the database is doing full table scans instead of using indexes.
Create indexes on fields that are frequently searched (incident state, assignee group) or frequently joined (user table). Avoid indexing rarely searched fields (it wastes space and slows down writes). Use the slow query log to find which queries are expensive and need indexes.
Write efficient queries: filter early (WHERE clause), add the narrowest encoded query you can, set a row limit where the script needs only a sample, and avoid running a second query inside a loop over records. Test queries with realistic data volume before deploying.
Implement Caching Strategy
Caching stores frequently used data in memory so it does not need to be queried from the database every time. This can cut repeated reads on the database.
Cache frequently accessed data: lookup tables (statuses, departments), configuration data (business rules, settings), reference data (countries, timezones). Do not cache data that changes frequently (incident status, user location) or sensitive data (passwords, compensation).
Invalidate cache when data changes: when a status lookup is added, invalidate the status cache so it is refreshed. Use cache with caution: stale cache causes users to see old data. Plan cache refresh strategies (refresh daily, refresh on demand, refresh when related data changes).
Minimise Complex Business Rules and Scripts
Business rules and scripts run on every transaction. Complex or inefficient ones slow everything down. A business rule that queries a large table on every record create will be slow when creating many records.
Keep rules simple. If a rule queries data, make sure that query is efficient (indexed, filtered). If a rule runs expensive calculation, consider running it asynchronously (in background) instead of synchronously (blocking the user). Move calculation from server-side code to database-level (let the database do aggregation) when possible.
Use Asynchronous Processing for Non-Critical Work
Some work does not need to happen immediately. Email notifications, document generation, report preparation can happen in background. This frees up the user-facing system to be responsive.
Design: User submits a request → system acknowledges immediately (user sees confirmation) → work is queued to background job → background job processes at its own pace → user is notified when complete. This is better than user waiting for work to complete.
Background jobs should be monitored: are they completing? How long are they taking? Are they failing? A failed background job should not go unnoticed; alert someone.
Monitor Capacity and Plan for Growth
As the system grows (more users, more data, more integrations), performance can degrade. Proactive capacity planning prevents this.
Monitor metrics: database size (is it growing? at what rate?), concurrent users (peak load?), transaction and integration volume at peak. Forecast future usage and raise capacity questions with ServiceNow in good time.
When usage is approaching the limits you have seen in testing, archive and reduce data volume, reschedule heavy jobs, and discuss instance sizing with ServiceNow. Better to upgrade proactively than to react to performance complaints from users.
Clean Up and Archive Old Data
Old data slows down queries. Records that are no longer active should be archived or deleted to keep the active database fast. Closed incidents past your retention period should not stay in the active incident table; move them to archive.
Archive strategy: identify data that is rarely accessed (old records, closed items). Move to archive table or external database. Update queries and reports to fetch from archive if needed. This keeps the active system fast.
Test Performance Changes Before Deployment
Performance regressions can be introduced by seemingly innocent changes. A new business rule, an additional join in a query, or a new integration can slow things down. Test performance before deploying.
In staging environment, deploy the change and run performance tests: create records, query lists, run reports. Measure and compare to baseline. If performance degrades significantly, investigate and fix before deploying to production.
Putting performance questions into the change review
Many performance regressions enter through ordinary changes: a new condition on a business rule, an extra column in a list, a script that now runs for every row in an import. The reviewer who catches them is often the person who knows which table is large and which screen is busy. Building that question into the review, rather than relying on that one person, is the practice that scales. The table below lists the questions to ask for each kind of change and the evidence that answers them well enough to approve the change.
| Change type | Question to ask | Evidence that is good enough |
|---|---|---|
| New or edited business rule on a busy table | Does it run on every write, or only when a condition is met? | The condition is written in the change, and a test run touched only the expected records |
| New list column or filter | Does it need a field that is not already used for filtering or sorting? | A timing for the list before and after, with the same filter applied |
| Script that loops over records | What is the largest set it will ever see, and does each pass read from the database? | A run against a copy of production-sized data, with the loop count recorded |
| New integration call | Is the call made in the user’s request, or can it be deferred? | A statement of the timeout, the retry rule and what the user sees if the call fails |
| New scheduled job | What is the window, and what else runs in it? | The job schedule with the existing jobs listed beside it |
A review checklist that does not slow the team down
A review that asks too many questions gets skipped. Keep the checklist short and make the reviewer name which items they checked, so the review leaves a trace.
- Does the change touch a table that users search or report on every day?
- Does it run on a write, a read, a schedule or a user action, and is that the intended trigger?
- Is there a timing, before and after, for the first screen or job it affects?
- If it calls another system, what happens to the user when that system is slow?
- Is there a way to turn the change off without a full release, and has that been tested?
Deciding between synchronous and deferred work
Deferring work can make a screen feel faster, but it also moves the failure to a later point where it is harder to see. The choice is about what the user needs to know at the moment they click, and what can be confirmed afterward.
| The user needs to know now | Better fit | What the team must add |
|---|---|---|
| Whether the save succeeded | Synchronous work for the save itself | Keep the save path short and free of optional calls |
| Whether a notification was queued | Queue on save, send in background | A visible record of queued messages and a way to find failures |
| Whether an external record was created | Synchronous only if the business cannot proceed without it | A timeout that is shorter than the user’s patience |
| Whether a nightly summary is correct | Background job | An owner who checks the job’s outcome each morning |
Keeping the practice alive after the first year
Review guidance decays. The checklist that was written for one team’s habits stops matching the platform once a new group of developers joins or a large feature changes the data model. Revisit the table once a year against the changes that were actually made, and retire any question that never led to a change. The aim is a short list that people still use, not a long one that everyone skips. Where a question keeps producing the same finding, the common mistakes guide is the place to turn it into a standing rule.
Should every change need a performance test?
No. A test is worth the time when the change touches a large table, a busy screen or a scheduled window. For a label change or a small form layout, a timing check on the affected screen is enough.
What if the test data is much smaller than production?
Then the test shows the shape of the problem, not its size. Note the gap in the review, and where the change is risky, ask for a run against a copy that is closer to real volume before approval.
Who should own the checklist?
The person who answers for the platform’s speed to users, usually the platform lead, with input from the developers who use it. A checklist owned by nobody gets quietly ignored.
Is asynchronous work always better for users?
No. Work that the user must see confirmed before moving on should stay synchronous. Deferral is for work the user does not need to wait on, and it must come with a way to find out when it fails.
The platform performance overview places this practice alongside the monitoring and capacity work it depends on, and the article on keeping ServiceNow performance steady gives a broader view of the same ground.
Performance tuning: tables, fields and values to measure first
ServiceNow performance work starts from measured request times, not guesses. The syslog_transaction table records the response time of each request, so sorting it by response time points to the slowest screens, lists and integrations before you change any business rule, index or schedule.
These are common out-of-box names and values. Check them on your own instance and release, since menu labels and defaults move between releases.
| Name | What it is | How to use it |
|---|---|---|
syslog_transaction |
One row per request, found under System Logs as Transactions, with the URL and response time | Build the baseline and find repeat offenders |
| Business rule When values | before, after, async and display | Keep optional work out of before rules, which run inside the user’s request |
sys_trigger |
The trigger rows that hold each scheduled job’s next run | Look for heavy jobs landing in the same window |
GlideAggregate |
A server API that counts, sums and groups in the database | Replace loops that read every row just to count them |
setLimit() |
A GlideRecord method that caps rows returned | Use it when a script needs only a sample |
Example (hypothetical): users say incident lists feel slow after a Thursday change. You sort the transaction log by response time and see the same list request near the top. The change added a before business rule that loops over related records with GlideRecord and counts them. You replace the loop with a GlideAggregate count, move the optional part to an async rule, and compare the same list request before and after on a copy of production data.
How do I find which rule slows a form save?
Start with the slow transaction, then list the rules that run on that table’s write. Before rules run inside the user’s request, so they are the first suspects. Disable or time them one at a time in a test instance, and confirm the change with a repeat measurement.
When is GlideAggregate better than GlideRecord?
Use GlideAggregate when the script needs a count, sum, minimum or grouped result. The database does the work and returns a small answer. GlideRecord is the right choice when the script must read or update each record, and a query with a narrow encoded query keeps that read small.
Does an async business rule stop the user waiting?
It removes the work from the user’s save, because the rule is queued and runs afterward. The work still uses node resources and can sit behind other jobs, so watch the queue and the outcome. For wider help, see performance tuning and upgrade support and the platform performance guides.
Frequently asked questions
How often should we archive old data?
Depends on data growth rate and access patterns. A fast-growing system might archive quarterly or monthly. A slow-growth system might archive annually. The key is: when the active database becomes large (millions of records), archive older data to keep performance good.
Should we use ServiceNow's built-in performance monitoring tools?
Yes. ServiceNow includes its own tools: the slow query, slow script and slow transaction records under system diagnostics, a performance dashboard, Instance Observer, and a page-load analyzer for the user interface. These tools track performance and alert when thresholds are exceeded. Use them. Also use external monitoring (browser tools, database monitoring) for additional visibility.
Can we improve performance by upgrading hardware?
Sometimes. Instance infrastructure is operated by ServiceNow, so hardware is not a lever the customer pulls directly. If testing shows the instance is saturated, the conversation is about instance sizing with ServiceNow, after configuration causes have been ruled out. But hardware upgrades are expensive and temporary if the root cause is inefficient code. Start by optimizing queries and code. Upgrade hardware as a last resort.
Related guides
Related Oblytech services
Where this topic turns into delivery work, these are the Oblytech services that cover it.
Planning, running or fixing a ServiceNow programme? Tell us where you are and we will suggest a sensible next step.
Contact us