- Establish the business case and commercial timeline for structured pre-renewal licence audits.
- Implement programmatic inactivity scanning utilizing precise SOQL queries to isolate dormant accounts.
- Design and deploy automated licence harvesting workflows using Apex batch jobs and user freeze protocols.
- Analyse strategies to right-size your tier mix by downgrading CRM users to cost-effective Platform and Identity licences.
- Embed licence optimisation as a core process within the Platform Center of Excellence (CoE) operating model.
The Rationale for Licence Audits: Eliminating Waste Before Renewals
In enterprise IT budgets, software-as-a-service (SaaS) licence spend represents a substantial recurring capital outlay. Among these, Salesforce is frequently one of the largest single lines. Yet, despite the high cost per seat, many organisations manage their Salesforce licence inventory passively. Rather than conducting deep usage analysis, businesses often auto-renew their existing counts or add a generic percentage buffer "just in case". This passive management style leads to significant "shelfware"—purchased licences that are completely unused or underutilised—often accounting for 20% to 30% of total spend.
The Real Financial and Operational Impact
To understand the commercial necessity of a licence audit, let us examine the numbers. A standard Sales Cloud Enterprise edition licence carries a list price of approximately £135 per user per month. If an enterprise organisation holds 200 unused or severely underutilised licences, this represents £27,000 in monthly waste, or £324,000 annually in pure losses. Over a three-year contract cycle, this waste exceeds £970,000. This capital could have been spent on strategic enhancements, technical debt remediation, or new functional capabilities.
Beyond the financial cost, maintaining redundant active user accounts presents significant operational and security risks:
- Security Exposure: Dormant user accounts that remain active are primary targets for credential compromise and data leakage. If a former contractor's account is not deactivated, they may retain access to sensitive customer data.
- Platform Performance: Redundant accounts increase clutter in user assignment tables, public group configurations, sharing rules, and security queues, making regular platform maintenance more complex.
- Unnecessary Add-on Costs: Premium add-on products (such as Salesforce Shield, Einstein, or sandbox licences) are often billed as a percentage of your overall licence pool. Reducing your core licence count instantly lowers these add-on costs.
The Strategic Audit Timeline
To capture these savings, you must align your audit with your contract renewal cycle. Conducting an audit 30 days before renewal is too late; your Account Executive has likely already drafted the renewal contract, and your internal teams will not have enough time to test and execute user downgrades. The Center of Excellence (CoE) should implement the following timeline:
| Timeline Phase | Key Activities | Deliverable Outcomes |
|---|---|---|
| 120 Days to Renewal | Initiate automated usage tracking and identify candidate users for harvesting or downgrading. | Baseline usage report and target savings model. |
| 90 Days to Renewal | Execute inactive freeze workflows, engage business unit heads, and start user acceptance testing (UAT) for profile downgrades. | Validated list of users to downsize or migrate. |
| 60 Days to Renewal | Deactivate confirmed dormant accounts, migrate low-touch users to Platform licences, and submit revised counts to Salesforce. | Formal contract negotiation proposal with exact seat counts. |
| 30 Days to Renewal | Finalise contract sign-off, run clean-up scripts, and lock down the new platform architecture. | Executed renewal contract reflecting optimised spend. |
Programmatic Inactivity Scanning: Tracking User Logins and Feature Activity
The foundation of any successful licence audit is objective, quantitative data. Business unit managers will often claim that every user "absolutely needs" their full Sales Cloud licence. To overcome this resistance, system administrators and architects must use programmatic inactivity scanning to gather undeniable usage evidence.
Defining the Audit Scope
A thorough audit must identify two distinct categories of user inactivity:
- Dormant Users (Dormancy): Active users who have not logged into the Salesforce platform for an extended period, typically defined by the CoE as 90 days or more.
- Underutilised Users (Dormant Activity): Users who log in regularly but never access or modify the core business features that justify their licence cost. For example, a user with a full Sales Cloud licence who has logged in fifty times but has not touched a Lead, Opportunity, or Campaign record in six months.
Programmatic Auditing via SOQL
To identify dormant users, administrators can run precise SOQL queries against the standard User object. Below is a production-ready query designed to isolate active users (excluding system administrative integrations) who have not logged in for over 90 days:
-- Query active, non-admin users who have not logged in for 90 days
SELECT Id, Name, Username, Email, Profile.Name, UserRole.Name, LastLoginDate, CreatedDate
FROM User
WHERE IsActive = true
AND LastLoginDate < LAST_90_DAYS
AND Profile.Name != 'System Administrator'
AND Profile.Name != 'B2B Integration User'
ORDER BY LastLoginDate ASC
For users who were provisioned but have never logged in, run this variation to assess training gaps or onboarding issues:
-- Query active users who have never logged in since account creation
SELECT Id, Name, Username, Email, CreatedDate, LastLoginDate
FROM User
WHERE IsActive = true
AND LastLoginDate = null
AND CreatedDate < LAST_90_DAYS
ORDER BY CreatedDate ASC
Analysing Feature Activity and CRM Object Interaction
Identifying underutilised users requires querying record ownership and modification logs. If a user holds a high-cost CRM licence but does not own or modify standard CRM records, they are an ideal candidate for a downgrade to a Salesforce Platform licence. You can run the following SOQL queries to compile this evidence:
-- Count active Opportunities modified by users in the last 90 days
SELECT OwnerId, COUNT(Id) OpportunityCount
FROM Opportunity
WHERE LastModifiedDate = LAST_90_DAYS
GROUP BY OwnerId
-- Count active Cases touched by users in the last 90 days
SELECT OwnerId, COUNT(Id) CaseCount
FROM Case
WHERE LastModifiedDate = LAST_90_DAYS
GROUP BY OwnerId
Architectural Tip: Cross-reference these activity counts with your user licence list. If a group of users has logged in but has zero interactions with Opportunity, Lead, Case, or Campaign records, they should be downgraded to a Salesforce Platform licence immediately. This move preserves their access to Accounts, Contacts, and custom objects while cutting licence costs by up to 50%.
Licence Harvesting Workflows: Automating Downgrades for Inactive Accounts
Manual clean-up efforts are highly time-consuming and often get neglected when administrators face more urgent requests. To maintain a clean environment, the platform architect should design and deploy an automated **Licence Harvesting Workflow**.
The Freeze vs. Deactivate Architecture
When automating licence clean-up, it is critical to understand the architectural difference between **freezing** a user and **deactivating** them:
- Deactivation (
IsActive = false): Deactivating a user immediately releases their licence back into the pool. However, if that user is referenced in active configurations (such as a default lead owner, a running user of a dashboard, a key workflow alert recipient, or a member of a custom hierarchy field), the deactivation will fail, throwing a system exception and blocking the automated process. - Freezing (
IsFrozen = trueonUserLogin): Freezing a user account blocks system access immediately, stopping the user from logging in and mitigating security risks. However, freezing does *not* release the licence back into the pool, nor does it trigger deactivation errors. Freezing always succeeds, regardless of system dependencies.
Therefore, a best-practice automated harvesting workflow should **freeze** inactive users first, and then send a notification to system administrators to handle deactivation dependencies manually.
Automated Apex Harvesting System
Below is a production-ready Apex Batch and Schedulable class that automatically scans for users who have not logged in for 90 days, freezes their accounts, and creates an audit record for administrative review:
global class InactiveUserFreezerBatch implements Database.Batchable<sObject>, Database.Stateful {
global Database.QueryLocator start(Database.BatchableContext BC) {
// Query active, non-admin users inactive for 90+ days
return Database.getQueryLocator([
SELECT Id, Name, Username, LastLoginDate
FROM User
WHERE IsActive = true
AND LastLoginDate < :Datetime.now().addDays(-90)
AND Profile.Name != 'System Administrator'
AND Profile.Name != 'B2B Integration User'
]);
}
global void execute(Database.BatchableContext BC, List<User> scope) {
List<Id> userIds = new List<Id>();
for (User u : scope) {
userIds.add(u.Id);
}
// Retrieve the corresponding UserLogin records
List<UserLogin> loginsToFreeze = [
SELECT Id, UserId, IsFrozen
FROM UserLogin
WHERE UserId IN :userIds AND IsFrozen = false
];
for (UserLogin ul : loginsToFreeze) {
ul.IsFrozen = true;
}
if (!loginsToFreeze.isEmpty()) {
// Update UserLogin to execute the freeze
update loginsToFreeze;
System.debug('Successfully froze ' + loginsToFreeze.size() + ' inactive user accounts.');
}
}
global void finish(Database.BatchableContext BC) {
// Send a consolidated email alert to the CoE / Admin team
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] {'salesforce-coe@organisation.com'});
mail.setSubject('Salesforce License Harvesting: Automated Freeze Execution Complete');
mail.setPlainTextBody('The weekly automated license harvesting batch ran successfully. Inactive users have been frozen. Please review the Inactive Users report to resolve deactivation dependencies and release seat allocations.');
Messaging.sendEmail(new List<Messaging.SingleEmailMessage> {mail});
}
}
To run this batch job automatically every weekend, deploy the following schedulable class wrapper:
global class InactiveUserFreezerScheduler implements Schedulable {
global void execute(SchedulableContext SC) {
InactiveUserFreezerBatch batch = new InactiveUserFreezerBatch();
Database.executeBatch(batch, 50); // Small batch size to manage governor limits
}
}
Right-Sizing the Tier Mix: Moving Users from CRM to Low-Cost Tiers
Not every user who requires access to Salesforce needs a high-cost Sales or Service Cloud licence. A critical phase of your licence audit is right-sizing the tier mix. This means mapping your users' actual data access needs against the most cost-effective licence types available.
Understanding the Licence Tiers
Salesforce offers a clear hierarchy of user licence tiers. By matching business personas to the appropriate tier, solution architects can achieve massive cost savings:
- Full CRM Licences (Sales Cloud / Service Cloud Enterprise): (Cost: ~£135/user/month). Grants full access to standard objects, including Leads, Opportunities, Campaigns, Cases, Accounts, and Contacts. This tier must be reserved strictly for core sales reps, pipeline managers, and customer service agents.
- Salesforce Platform Licences: (Cost: ~£35/user/month). Grants full access to Accounts, Contacts, and up to 110 custom objects per application. It strictly blocks access to Leads, Opportunities, and Cases. This tier is ideal for internal operations teams, HR coordinators, procurement managers, and back-office staff who interact with custom business apps but do not manage sales pipelines or customer service queues.
- Force.com / App Cloud Starter: (Cost: ~£25/user/month). Provides access to a limited subset of custom objects (typically up to 10). Designed for highly focused, single-purpose application users.
- Identity / Customer Community Licences: (Cost: ~£5-£10/user/month). Designed for external partners or users who only require single-sign-on (SSO) or access to read dashboards and submit requests, without direct database record manipulation privileges.
Compliance Reminder: When downgrading a user from a full CRM licence to a Platform licence, you must ensure they do not require standard object access. Attempting to build custom workarounds (e.g., exposing Lead records to Platform users via custom API pages or sharing rules) is a violation of Salesforce's "indirect access" rules and can result in severe audit penalties.
Right-Sizing Licence Mapping Matrix
The table below displays how a Center of Excellence can re-map common corporate personas to low-cost licence tiers during an audit:
| Corporate Persona | Standard Licence Assignment | Audit Analysis & Access Profile | Right-Sized Licence Target | Annual Savings per User |
|---|---|---|---|---|
| Core Account Manager | Sales Cloud Enterprise | Actively manages pipeline, creates opportunities, logs sales calls. | Retain Sales Cloud | £0.00 (No change) |
| Inventory Manager | Sales Cloud Enterprise | Requires access only to asset tracking custom objects and standard Accounts. | Salesforce Platform | £1,200.00 (74% saving) |
| HR Specialist | Sales Cloud Enterprise | Manages internal recruitment processes built entirely on custom objects. | Salesforce Platform | £1,200.00 (74% saving) |
| Executive Reviewer | Sales Cloud Enterprise | Only logs in once a month to view read-only dashboards and approve tasks. | Platform + Dashboard Subscriptions | £1,200.00 (74% saving) |
| Standard Employee | Salesforce Platform | Only logs in to use single-sign-on (SSO) to access external company apps. | Salesforce Identity | £300.00 (71% saving) |
Continuous Optimization: Embedding Licence Auditing in Platform CoE Governance
A common pitfall in licence optimisation is treating the audit as a one-off event. An organisation might run an audit, save £100,000, and then return to passive management. Within twelve months, business units will request more licences, dormant accounts will accumulate, and the waste will return.
To prevent this, the Salesforce Center of Excellence (CoE) must embed licence management directly into its regular platform governance processes. Licence optimisation must become a standard operating procedure.
Building the Licensing KPI Dashboard
System administrators should build a dedicated Platform Health and Licensing Dashboard. This dashboard must be reviewed by the CoE steering committee every month. It should display the following key performance indicators (KPIs):
- Licence Utilisation Rate: A gauge component showing active assigned seats versus total purchased seats for each licence type.
- Dormancy Tracking: A chart displaying the number of active users who have not logged in for 30, 60, and 90 days.
- Onboarding Bottlenecks: A table listing new accounts created in the last 45 days that have zero login history.
- CRM Object Activity Index: A component highlighting CRM licence holders who have had zero database interactions (Opp, Lead, Case) in the last quarter.
Implementing an Internal Chargeback Model
One of the most effective ways to drive licence efficiency is to align financial accountability with usage. Many organisations fund their Salesforce licences through a central IT budget. Business unit managers have no incentive to release unused seats because the cost does not affect their departmental budgets.
The CoE should partner with finance to implement an Internal Chargeback Model. Under this model:
- The central IT department purchases Salesforce licences in bulk to secure volume discounts.
- Each business unit is billed monthly for the *actual* number of active user accounts assigned to their department.
- If a manager has ten dormant users, their department budget continues to pay for those seats. This financial model immediately motivates business managers to approve deactivations and right-size their user tiers.
Governance Policy: Establish a standard CoE policy: "Any user account that remains inactive for 90 days will be automatically frozen. The business unit will have 30 days to request unfreezing before the account is deactivated and the licence is reallocated to another department." This simple rule eliminates waste automatically, keeping your system lean and secure.
Key Takeaways
- Passive Salesforce licence management leads to 20% to 30% of total contract spend being wasted on shelfware.
- Programmatic scanning using SOQL queries is essential to isolate dormant users who have not logged in for 90+ days.
- Freezing users via the UserLogin metadata object avoids system deactivation errors caused by workflow and ownership rules.
- Right-sizing user tiers by migrating non-CRM users to Platform licences can reduce individual seat costs by up to 74%.
- Continuous optimization requires embedding monthly licence audits and internal chargeback models within CoE governance.
Checkpoint: Test Your Understanding
1. Why is "freezing" a user via the UserLogin object commercially and technically preferred as the first step of an automated licence harvesting workflow?
2. If an internal user only requires access to standard Accounts, Contacts, and custom database schemas, which licence tier represents the most cost-effective compliance target?
3. To secure maximum savings, how many days prior to a contract renewal should a Salesforce Center of Excellence (CoE) initiate its licence audit?
Discussion & Feedback