What are Business Rules?

Business Rules are server-side scripts that run when records are queried, updated, inserted, or deleted. They automate business logic and data processing.

Critical Concept

Business Rules are THE most important server-side automation in ServiceNow. They run on the server, have full database access, and execute automatically based on conditions.

Four Types of Business Rules

Type When Use Case
Before Before database write Validate data, set field values, prevent save
After After database write Create related records, send notifications
Async After commit, background Long-running operations, external integrations
Display When form loads Set UI properties, control form behavior

Before Business Rules

Run before the record is written to the database. Can modify field values or prevent the operation.

Before Insert/Update Example
// Business Rule: Auto-assign High Priority Incidents
// Table: incident
// When: before
// Insert: true, Update: true
// Condition: current.priority == '1'

(function executeRule(current, previous /*null when async*/) {
    
    // Ensure assignment for critical incidents
    if (current.assignment_group.nil()) {
        current.assignment_group = 'high_priority_group_sys_id';
        gs.info('Auto-assigned high priority incident: ' + current.number);
    }
    
    // Set state to In Progress
    if (current.state == '1') { // New
        current.state = '2'; // In Progress
    }
    
})(current, previous);
Before - Prevent Save
// Business Rule: Prevent Closing Without Resolution
// Table: incident
// When: before
// Update: true
// Condition: current.state == '7' (Closed)

(function executeRule(current, previous /*null when async*/) {
    
    // Validate resolution information
    if (current.close_notes.nil() || current.close_code.nil()) {
        gs.addErrorMessage('Cannot close incident without resolution notes and close code');
        current.setAbortAction(true); // Prevent save
        return;
    }
    
    // Ensure resolved date is set
    if (current.resolved_at.nil()) {
        current.resolved_at = gs.nowDateTime();
    }
    
})(current, previous);
Before Rules Best Practices

Use for: data validation, setting field values, calculations. Do NOT query other tables excessively. Use current.setAbortAction(true) to prevent save. Changes to 'current' are saved automatically.

After Business Rules

Run after the record is written to the database. Cannot modify the current record (must use update()).

After Insert - Create Related Records
// Business Rule: Create Incident Tasks
// Table: incident
// When: after
// Insert: true
// Condition: current.priority == '1'

(function executeRule(current, previous /*null when async*/) {
    
    // Create initial investigation task
    var task = new GlideRecord('incident_task');
    task.initialize();
    task.parent = current.sys_id;
    task.short_description = 'Initial investigation for ' + current.number;
    task.assignment_group = current.assignment_group;
    task.priority = '1';
    task.insert();
    
    gs.info('Created task for critical incident: ' + current.number);
    
})(current, previous);
After Update - Track Changes
// Business Rule: Log Priority Changes
// Table: incident
// When: after
// Update: true
// Condition: current.priority.changes()

(function executeRule(current, previous /*null when async*/) {
    
    // Log the priority change
    var oldPriority = previous.priority.toString();
    var newPriority = current.priority.toString();
    
    gs.log('Priority changed from ' + oldPriority + ' to ' + newPriority + 
           ' for incident: ' + current.number + ' by ' + gs.getUserName());
    
    // Add work note
    current.work_notes = 'Priority escalated from ' + oldPriority + ' to ' + newPriority;
    current.update(); // Note: This triggers business rules again!
    
})(current, previous);
After Rules Best Practices

Use for: creating related records, triggering workflows, sending notifications. To modify current record, use current.update(). Be careful of infinite loops! Use .changes() to detect field modifications.

Async Business Rules

Run in the background after the database transaction completes. Don't block the user.

Async Example
// Business Rule: External System Integration
// Table: incident
// When: async
// Insert: true, Update: true
// Condition: current.priority <= '2'

(function executeRule(current, previous /*null when async*/) {
    
    // Note: 'previous' is not available in async
    
    // Call external API
    try {
        var request = new sn_ws.RESTMessageV2();
        request.setEndpoint('https://external-system.com/api/incident');
        request.setHttpMethod('POST');
        
        var body = {
            number: current.number.toString(),
            priority: current.priority.toString(),
            description: current.short_description.toString()
        };
        
        request.setRequestBody(JSON.stringify(body));
        var response = request.execute();
        
        gs.info('Sent incident to external system: ' + response.getStatusCode());
        
    } catch (ex) {
        gs.error('Failed to send to external system: ' + ex.message);
    }
    
})(current, previous);
Async Rules Best Practices

Use for: external integrations, long-running operations, email sending. 'previous' is NOT available. User doesn't wait for completion. gs.addInfoMessage() won't display to user.

Display Business Rules

Run when a form is loaded, before it's sent to the client. Can use g_form methods.

Display Example
// Business Rule: Set Form Properties
// Table: incident
// When: display
// Condition: current.state == '6' || current.state == '7'

(function executeRule(current, previous /*null when async*/) {
    
    // Make fields read-only for closed incidents
    g_scratchpad.isResolved = true;
    
    // This data is available client-side via g_scratchpad
    g_scratchpad.resolvedBy = current.resolved_by.getDisplayValue();
    g_scratchpad.resolutionTime = current.resolved_at.toString();
    
})(current, previous);
Display Rules Best Practices

Use for: passing data to client scripts via g_scratchpad. Limited use cases. Prefer UI Policies for form control. Don't perform heavy queries.

Detecting Field Changes

Change Detection Methods
// Check if ANY field changed
if (current.changes()) {
    gs.info('Record was modified');
}

// Check if specific field changed
if (current.priority.changes()) {
    gs.info('Priority changed');
}

// Check if field changed FROM a value
if (current.state.changesFrom('2')) {
    gs.info('State changed from In Progress');
}

// Check if field changed TO a value
if (current.state.changesTo('6')) {
    gs.info('State changed to Resolved');
}

// Check if field changed from one value to another
if (current.state.changesFrom('2').changesTo('6')) {
    gs.info('State changed from In Progress to Resolved');
}

// Get old value
if (current.priority.changes()) {
    var oldValue = current.priority.getOldValue();
    var newValue = current.priority.getValue();
    gs.info('Priority changed from ' + oldValue + ' to ' + newValue);
}

// Using previous object (not available in async)
if (previous && previous.priority != current.priority) {
    gs.info('Priority changed from ' + previous.priority + ' to ' + current.priority);
}

Business Rule Order and Control

Controlling Execution
// Prevent save (before rules only)
current.setAbortAction(true);

// Prevent other business rules from running
current.setWorkflow(false);

// Check if running from async business rule
if (!gs.isInteractive()) {
    // Running in background
}

// Order field: Controls execution order (100, 200, 300...)
// Lower numbers run first

// Advanced: Skip business rules on update
current.setWorkflow(false);
current.autoSysFields(false); // Don't update sys fields
current.update();

CSA & CAD Exam Questions (16 Questions)

When do before business rules execute? Q1
CSA
  • A) After the database is updated
  • B) Before the database is updated
  • C) When the form loads
  • D) In the background
Show Answer
Correct Answer: B
Before business rules execute before the record is written to the database. They can modify field values or prevent the operation with setAbortAction(true).
How do you prevent a record from being saved in a before business rule? Q2
CSA
  • A) return false
  • B) current.setAbortAction(true)
  • C) current.cancel()
  • D) gs.preventDefault()
Show Answer
Correct Answer: B
Use current.setAbortAction(true) in a before business rule to prevent the record from being saved. Combine with gs.addErrorMessage() to inform the user.
In after business rules, how do you modify the current record? Q3
CSA
  • A) Changes to current are saved automatically
  • B) Must call current.update()
  • C) Cannot modify current in after rules
  • D) Use current.save()
Show Answer
Correct Answer: B
In after business rules, changes to current are NOT saved automatically. You must call current.update() to save changes. Be careful of infinite loops!
When should you use async business rules? Q4
CAD
  • A) For data validation
  • B) For long-running operations that shouldn't block the user
  • C) To modify field values before save
  • D) To control form display
Show Answer
Correct Answer: B
Async business rules run in the background after the transaction completes. Use for external integrations, email sending, or long-running operations that shouldn't delay the user.
Is the 'previous' object available in async business rules? Q5
CAD
  • A) Yes, always
  • B) No, it's null in async rules
  • C) Only for update operations
  • D) Only if specified in conditions
Show Answer
Correct Answer: B
The 'previous' object is null in async business rules. Use current.changes() methods instead to detect what changed.
How do you check if a specific field changed? Q6
CSA
  • A) current.field.changed()
  • B) current.field.changes()
  • C) current.field.wasModified()
  • D) current.hasChanged('field')
Show Answer
Correct Answer: B
Use current.field.changes() to check if a field was modified. Returns true if the field value changed in this transaction.
What is g_scratchpad used for? Q7
CAD
  • A) Temporary database storage
  • B) Passing data from display business rules to client scripts
  • C) Storing user preferences
  • D) Caching query results
Show Answer
Correct Answer: B
g_scratchpad is a server-side object available in display business rules. Data added to it is accessible client-side in client scripts.
What controls the order in which business rules execute? Q8
CAD
  • A) Name alphabetically
  • B) Order field (lower numbers first)
  • C) Created date
  • D) Random order
Show Answer
Correct Answer: B
The Order field determines execution sequence. Lower values (100, 200) execute before higher values (300, 400). Default is 100.
Can you use GlideRecord in business rules? Q9
CSA
  • A) No, only in Script Includes
  • B) Yes, business rules run server-side
  • C) Only in after business rules
  • D) Only with admin role
Show Answer
Correct Answer: B
Yes! Business rules run server-side and have full access to GlideRecord, gs, and all server APIs. This is a key difference from client scripts.
What happens if you call current.update() in a before business rule? Q10
CAD
  • A) It saves the record immediately
  • B) It's unnecessary - changes save automatically
  • C) It causes an error
  • D) It triggers business rules again
Show Answer
Correct Answer: B
In before business rules, changes to current are saved automatically when the rule completes. Calling update() is unnecessary and can cause issues.
How do you get the old value of a field that changed? Q11
CSA
  • A) previous.field
  • B) current.field.getOldValue()
  • C) Both A and B
  • D) current.field.previous()
Show Answer
Correct Answer: C
Both work: previous.field (when previous is available) or current.field.getOldValue(). The getOldValue() method works even in async where previous is null.
Can display business rules use g_form methods? Q12
CAD
  • A) No, g_form is client-side only
  • B) Yes, display rules have access to g_form
  • C) Only for read operations
  • D) Only with a special setting
Show Answer
Correct Answer: B
Yes, display business rules can use g_form methods because they run during form load preparation. However, UI Policies are generally preferred for form control.
What does current.setWorkflow(false) do? Q13
CAD
  • A) Stops all workflows
  • B) Prevents other business rules from running on update
  • C) Disables the workflow engine
  • D) Cancels the current workflow
Show Answer
Correct Answer: B
current.setWorkflow(false) prevents business rules from running on the subsequent update(). Use to avoid infinite loops when updating current in an after rule.
Can business rules run on delete operations? Q14
CSA
  • A) No, only insert and update
  • B) Yes, check the Delete checkbox
  • C) Only before delete
  • D) Only for admin users
Show Answer
Correct Answer: B
Yes, business rules can run on delete by checking the Delete checkbox. Use to prevent deletion, log deletions, or clean up related records.
What method checks if a field changed from a specific value? Q15
CAD
  • A) current.field.changedFrom(value)
  • B) current.field.changesFrom(value)
  • C) current.field.wasValue(value)
  • D) current.field.previousValue(value)
Show Answer
Correct Answer: B
Use current.field.changesFrom(value) to check if a field changed from a specific value. Can chain with changesTo(): current.state.changesFrom('2').changesTo('6').
Where do business rules execute? Q16
CSA
  • A) In the user's browser
  • B) On the ServiceNow server
  • C) In both browser and server
  • D) In the database
Show Answer
Correct Answer: B
Business rules execute on the ServiceNow server, not in the browser. This is why they have full access to the database via GlideRecord.

Quick Reference

  • Before: Modify data pre-save
  • After: Create related records
  • Async: Background tasks
  • Display: Form load setup
  • setAbortAction(true) - Stop save
  • changes() - Detect changes
  • update() - Save in after/async