CSA Guide

Scheduled Jobs and Background Scripts

Introduction

Not every automation in ServiceNow should fire in response to a record change. Some operations are inherently time-based: nightly data cleanup, weekly SLA summary emails, daily synchronization with external systems. Scheduled Jobs handle these recurring tasks. Background Scripts handle one-off administrative operations that you need to run directly against the server.


Scheduled Jobs

Scheduled Jobs (sysauto_script) run server-side JavaScript on a defined schedule.

System Definition > Scheduled Jobs > New

Key Fields

Field Description
Name Descriptive job name
Run Frequency (Daily, Weekly, Periodically, On Demand, Once)
Time When to run (for daily/weekly)
Run as User context for the job
Script Server-side JavaScript to execute
Active Enable/disable the job

Cron-Style Scheduling (Periodically)

For custom frequencies, use the "Periodically" option with a repeat interval, or use a CRON expression:

Every 15 minutes: */15 * * * *
Every day at 2am:   0 2 * * *
Every Monday 6am:   0 6 * * 1
First of month:     0 9 1 * *

Writing Scheduled Job Scripts

Example: Close Resolved Incidents After 7 Days

var gr = new GlideRecord('incident');
gr.addQuery('state', '6'); // Resolved
gr.addQuery('resolved_at', '<', gs.daysAgoStart(7));
gr.query();

var count = 0;
while (gr.next()) {
    gr.setValue('state', '7'); // Closed
    gr.setValue('close_notes', 
        'Auto-closed after 7 days in Resolved state.');
    gr.update();
    count++;
}

gs.info('Auto-close job: closed ' + count + ' incidents.');

Example: Daily SLA Breach Report Email

var ga = new GlideAggregate('task_sla');
ga.addQuery('has_breached', true);
ga.addQuery('stage', 'In Progress');
ga.addAggregate('COUNT');
ga.query();

var breachCount = 0;
if (ga.next()) {
    breachCount = parseInt(ga.getAggregate('COUNT'));
}

if (breachCount > 0) {
    gs.eventQueue(
        'sla.daily.breach.summary',
        null,
        breachCount.toString(),
        gs.now()
    );
}

Monitoring Scheduled Jobs

Job Execution History

System Definition > Scheduled Jobs → select job → Scheduled Job Executions (related list)

Each execution record shows:

  • Start and end time
  • Duration
  • Status (Success, Error)
  • Output messages from gs.info() and gs.error()

System Logs

System Logs > System Log > Application

Filter by source = your job name to see gs.info() / gs.error() output.


Run As User

Always set a dedicated service account as the Run As user — never use a named person's account:

  • Named user accounts can be disabled, locking the job
  • Service accounts have controlled, minimal permissions
  • Audit trails are cleaner when a service account performs automated actions

Create a user like svc_scheduled_jobs with only the roles required for the specific job's operations.


Background Scripts

Background Scripts (sys_script_plain) execute JavaScript immediately in the current session — no schedule, one-time execution.

System Definition > Background Scripts

Paste your script and click Run script. Output appears directly in the browser.

Use Cases

  • Data fixes: correct a batch of mis-populated field values
  • One-time migrations: move records to a new structure
  • Testing: verify GlideRecord queries before building Business Rules
  • Diagnostics: inspect system state, check property values

Example: Fix Assignment Group on Old Records

var gr = new GlideRecord('incident');
gr.addQuery('assignment_group.name', 'Old Group Name');
gr.addQuery('state', 'IN', '1,2,3'); // Open states
gr.query();

var newGroup = new GlideRecord('sys_user_group');
newGroup.get('name', 'New Group Name');
var newGroupId = newGroup.getUniqueValue();

var count = 0;
while (gr.next()) {
    gr.setValue('assignment_group', newGroupId);
    gr.update();
    count++;
}
gs.info('Updated ' + count + ' records.');

Safety Rules for Background Scripts

  • Always query first — comment out the update() or deleteRecord() call, run the query, log counts, then uncomment and execute
  • Never use deleteMultiple() without double-checking the query result set
  • Test in sub-prod first — background scripts against production data are irreversible
  • Document what you ran — add a comment to the script and save it before executing

Best Practices

  • Use a dedicated service account for all scheduled jobs
  • Log start and completion with gs.info() — include record counts
  • Add error handling with try/catch in scheduled job scripts
  • Keep scheduled jobs focused — one job per task
  • Monitor execution history after deploying new jobs
  • Use setLimit() on queries in scheduled jobs to prevent runaway operations
  • Test background scripts against a non-production instance before production

Conclusion

Scheduled Jobs and Background Scripts are the administrative backbone of a well-run ServiceNow instance. Used correctly — with proper service accounts, logging, error handling, and sub-prod testing — they automate the boring parts of platform administration and free your team to focus on higher-value work.

Keep reading this guide

Log in to access the full study guide and supercharge your preparation.