How Discovery Synchronizes Uninstalled Software in cmdb_sam_sw_install.<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } 1. Overview : When ServiceNow Discovery scans a Linux or Windows server, it does more than just collect and insert newly found software — it also reconciles the entire discovered software list against what is already stored in cmdb_sam_sw_install. This reconciliation is responsible for keeping the SAM software install table accurate and up to date as software is installed, upgraded, or removed from managed devices. However, the way this reconciliation works is more nuanced than a simple insert-or-delete operation. Whether a software record gets deleted when software is uninstalled depends on three distinct factors working together: 1.1. Discovery Source Ownership — The reconciler only evaluates records that were originally created by the same Discovery source running the current scan. Records created by other integrations are never touched. 1.2 The "created_by_application_patter" Flag — Records created by Application Patterns are intentionally protected from deletion by Discovery's reconciler. This is expected behavior, not a bug. 1.3. The Business Rule "Sync Installed Software" — For pattern-created records that Discovery cannot delete, this BR provides the alternate cleanup mechanism, but it only fires under specific trigger conditions. When all three factors are understood together, most cases of stale software records can be explained and resolved. This KB walks through each layer of the process in detail. 2. End-to-End Execution Flow : 2.1 The DiscoverySensor is the entry point for all sensor execution in ServiceNow Discovery, calls DiscoveryReconciler script include. 2.2 DiscoveryReconciler : DiscoveryReconciler acts as a traffic controller for all related list data collected during a Discovery scan. It looks at each table's data and decides how it should be processed — most tables go through a standard built-in reconciliation path, but software data is an exception. When it encounters software data, instead of processing it directly, it hands it off to GlideappCMDBSoftwareHelper — a dedicated class purpose-built for software reconciliation. Everything that happens to cmdb_sam_sw_install from that point onward is owned by CMDBSoftwareHelper. 2.3 CMDBSoftwareHelper — Before CMDBSoftwareHelper compares the discovered software list against the database, it first prepares each software record by enriching it with three key pieces of metadata: Vendor Normalization — Resolves each software vendor against the core_company table, creating a company record if one does not already exist. This ensures manufacturer data is always linked to a valid record rather than stored as a plain text string.Discovery Source Stamping — Each record is tagged with discovery_source based on the system property glide.discovery.source_name (default: ServiceNow). This tag is what the reconciler later uses to determine which records it owns and is allowed to update or delete. Records with a different discovery_source are never touched.Last Scanned Date Stamping — Each record is stamped with today's date as last_scanned, confirming that Discovery found this software in the current scan. If com.snc.sams is active, assigned_to is also populated from the parent CI.Important: Only records actively discovered in the current scan go through this pipeline. Records with created_by_application_pattern = true are excluded from the reconciler entirely — meaning last_scanned is never updated on them by Discovery. This directly impacts the reliability of any Table Cleaner job that uses last_scanned to identify stale records, covered in Section 5. 2.4 Reconciliation Against cmdb_sam_sw_install When com.snc.sam.core Plugin is active, the reconciler works against the cmdb_sam_sw_install table. It begins by querying the database for all existing software install records linked to the current CI, scoped to records owned by the current Discovery source: Query scope: installed_on = current CI sys_id discovery_source = <glide.discovery.source_name> OR discovery_source IS EMPTY It then compares this database result set against the incoming enriched software list using a composite key of display_name + version. This means the combination of the software's display name and its version is what uniquely identifies a record — if either changes between scans, the reconciler treats it as a different software entry. The outcome for each record depends on what the reconciler finds: Scenario Created_by_application_pattern Action In cmdb_sam_sw_install, found in current scan — only last_scanned changedfalseSkipped — last_scanned handled via batch updateIn cmdb_sam_sw_install, found in current scan — other fields changedfalseUpdated individuallyIn cmdb_sam_sw_install, NOT found in current scanfalseDeletedIn cmdb_sam_sw_install, NOT found in current scantrueSkipped — protected from deletionNot in cmdb_sam_sw_install, found in current scanEitherInserted as new record 2.5 Non-com.snc.sam.core Path : If com.snc.sam.core is not active, the reconciliation falls back to a legacy path that operates against cmdb_software_instance (a many-to-many table) and cmdb_ci_spkg rather than cmdb_sam_sw_install. In this path, the helper ensures all discovered software packages exist in cmdb_ci_spkg, collects their sys_ids, and reconciles the cmdb_software_instance records for the CI. Records not present in the current scan are deleted directly. Notably, the created_by_application_pattern protection does not apply in the legacy path. Deletions in cmdb_software_instance are not subject to this exception. 3. The created_by_application_pattern Flag : The created_by_application_pattern field on cmdb_sam_sw_install indicates the record was created by an Application Pattern rather than a standard probe-based Discovery scan. Because Application Patterns provide deeper and more authoritative software discovery than standard probes, their records are intentionally protected from deletion by Discovery's reconciler. If software is uninstalled and its cmdb_sam_sw_install record has created_by_application_pattern = true, Discovery will never remove it regardless of how many times the scan runs. The record will persist until one of the following occurs: The Application Pattern re-runs, detects the removal, and the BR "Sync Installed Software" fires and cascade-deletes the recordThe record is manually deletedA Table Cleaner or mass deletion job purges it based on age 4. Business Rule — "Sync Installed Software" : 4.1 Purpose This Business Rule is the primary automated cleanup mechanism for created_by_application_pattern = true records. It bridges the gap that Discovery's reconciler cannot cover — when an Application Pattern updates or removes a software CI, this BR ensures the corresponding cmdb_sam_sw_install record is kept in sync or deleted accordingly. 4.2 Trigger Condition The BR fires only when one of the following conditions is met on the triggering CI record: current.version.changes() || current.edition.changes() || current.operation() === 'delete' 4.3 Execution Logic If the triggering operation is a delete, the BR cascade-deletes the corresponding cmdb_sam_sw_install record. It Lookup For version or edition changes, the BR looks up cmdb_sam_sw_name_mapping using the CI's sys_class_name to resolve the correct display_name (product + edition) and publisher. This lookup must return exactly one result — if no match or more than one match is found, the BR logs a warning and exits without making any changes. The BR calls SAMCoreUtils.getInstalledOnRelationship() which queries cmdb_rel_ci for a "Runs on :: Runs" relationship where the software CI is the parent and the child is either a cmdb_ci_hardware or cmdb_ci_oslv_container instance. Two outcomes: OutcomeActionValid "Runs on" relationship foundUpdate cmdb_sam_sw_install with resolved display_name, publisher, version, installed_onNo valid relationship foundDelete the cmdb_sam_sw_install record The software CI may still exist in the CMDB with other relationships — but if it has no "Runs on" link to a hardware or container CI, the cmdb_sam_sw_install record is treated as orphaned and deleted. 5. Recommended Cleanup Approaches for Stale Records 5.1 Table Cleaner — sys_auto_flush (KB0694151) Table Cleaner is the recommended first approach for purging stale records when neither Discovery nor the BR has been able to remove them. Configure the job as follows: FieldRecommended ValueTablecmdb_sam_sw_installMatch fieldlast_scannedAge in seconds7776000 (90 days)ConditionOptionally filter to created_by_application_pattern = true to avoid impacting Discovery-managed records Since Discovery does not update last_scanned on pattern-created records, and the BR only fires on version/edition changes or deletes, last_scanned on these records reflects when the Application Pattern last ran — not the last Discovery scan. If the Application Pattern does not stamp last_scanned on re-run, records will never age out and the Table Cleaner job will not purge them. If the Table Cleaner is targeting a large volume of records, configure it to run in small batches to avoid database performance impact and transaction timeouts. This is especially important for one-time bulk cleanup scenarios. 5.2 Mass Deletion for Large Datasets (KB0717791) If a large volume of stale records has accumulated and Table Cleaner alone is insufficient or too slow, refer to KB0717791 for mass deletion and excess data management recommendations. This approach is intended for one-time cleanup scenarios only and should not replace a properly configured ongoing maintenance strategy. Always test cleanup jobs in a non-production environment first and ensure appropriate backup and restore procedures are in place before running any mass deletion in production. Refer: Uninstalled software still shows as active install in software installation table. Delete uninstalled software from the Software Installation table.