Can we prevent records getting deleted by Auto Flush (sys_auto_flush) without modifying the rule.

YashSha9462
Tera Contributor

Hello,

I have a requirement where we need to prevent the records which are getting deleted by the auto flush rule, I don't want to modify the auto flush rule. I just want to prevent the records which are getting deleted though auto flush rule or any of the archive rule.

This requirement came after we identified an issue in our system where, their were multiple auto flush rules were running in the production on multiple tables because of which our records got deleted. So, we inactivated those rule after that. But now we are looking for a solution where we can prevent these records from getting delete in future if someone creates any such auto flush rule.

Also, if a record is getting deleted we want to send out a notification for those records which are getting deleted. Now in this scenario there are multiple tables, can we create a single BR where we can store the values of the tables in a system property and that can trigger the notification.

1 REPLY 1

Naveen20
ServiceNow Employee

Try this complete approach


1. System Property for Protected Tables

First, create a system property to store the list of tables you want to protect. Navigate to sys_properties.list and create:

  • Name: x_custom.protected_tables
  • Value: incident,change_request,sc_req_item (comma-separated list of tables)

This gives you a central place to manage which tables are protected without modifying any business rules.


2. Shared Script Include for Reusable Logic

Create a Script Include that holds your protection and notification logic so every table's Business Rule can call into it:

var AutoFlushProtector = Class.create();
AutoFlushProtector.prototype = {
    initialize: function() {
        this.protectedTables = gs.getProperty('x_custom.protected_tables', '').split(',');
    },

    isProtectedTable: function(tableName) {
        for (var i = 0; i < this.protectedTables.length; i++) {
            if (this.protectedTables[i].trim() === tableName) {
                return true;
            }
        }
        return false;
    },

    isAutoFlushContext: function() {
        // Auto flush runs as 'system' with no interactive session
        var userName = gs.getUserName();
        var sessionUser = gs.getSession().isInteractive();
        return (userName === 'system' && !sessionUser);
    },

    handleDelete: function(current) {
        var tableName = current.getTableName();

        if (!this.isProtectedTable(tableName)) {
            return; // not a protected table, allow delete
        }

        if (this.isAutoFlushContext()) {
            // Fire event for notification before aborting
            gs.eventQueue(
                'x_custom.auto_flush_blocked',
                current,
                tableName,
                current.getDisplayValue()
            );

            gs.addErrorMessage('Delete blocked: Auto flush attempted to remove ' 
                + tableName + ' record: ' + current.getDisplayValue());
            current.setAbortAction(true);

            // Optional: log to a custom tracking table
            this._logBlockedDeletion(current, tableName);
        }
    },

    _logBlockedDeletion: function(current, tableName) {
        var log = new GlideRecord('x_custom_flush_block_log'); // optional custom table
        log.initialize();
        log.setValue('table_name', tableName);
        log.setValue('record_sys_id', current.getUniqueValue());
        log.setValue('display_value', current.getDisplayValue());
        log.setValue('blocked_on', new GlideDateTime());
        log.insert();
    },

    type: 'AutoFlushProtector'
};

3. Before Delete Business Rule (Per Table)

Unfortunately, a single Business Rule cannot run on multiple tables natively in ServiceNow. You need one BR per table. However, since all the logic lives in the Script Include, each BR is just a two-line wrapper.

Create a Before Delete Business Rule on each protected table:

  • Name: Protect from Auto Flush - [Table Label]
  • Table: e.g., incident
  • When: Before
  • Delete: true
  • Order: 50 (run early)

Script:

(function executeRule(current, previous) {
    var protector = new AutoFlushProtector();
    protector.handleDelete(current);
})(current, previous);

You repeat this BR on each table listed in the property. Since the script body is identical, it takes seconds to clone for additional tables.


4. Notification via Event

Register the event and tie a notification to it:

Event Registration sysevent_register.list

  • Name: x_custom.auto_flush_blocked
  • Table: Global or *

Notification sysevent_email_action.list

  • Name: Auto Flush Deletion Blocked
  • Event Name: x_custom.auto_flush_blocked
  • Recipients: Your admin group or DL
  • Subject: Auto Flush Blocked: ${event.parm1} - ${event.parm2}
  • Body: Include the table name (event.parm1) and display value (event.parm2) so the team knows exactly which record was targeted.