How to Reduce Salesforce License Costs Before Your Next Renewal
Salesforce is almost always the largest single line item in a company's SaaS stack. Most companies overpay by 20–30% — not because they negotiated badly, but because they walked in without data.
Your Salesforce renewal is coming. Your AE has already called. The number on the table is higher than last year — because Salesforce raised list prices 6% in August 2025, and your headcount grew, and someone added a few Unlimited seats “just in case.”
The companies that get the best renewals aren't the ones with the best negotiators. They're the ones who showed up with a spreadsheet of exactly which users logged in last month, which permission set licenses are assigned to people who never use them, and exactly how many seats they could cut without anyone noticing.
That's what this guide covers.
TL;DR: Salesforce license waste comes from four buckets: inactive users, over-licensed user types, unused PSLs, and integration accounts holding full user licenses. Audit each bucket before renewal, document your findings, and bring the numbers to the negotiation. Companies that do this typically recover 15–25% of their annual contract value.
Why Salesforce licenses are so easy to over-buy
Salesforce pricing is deliberately opaque. There's no self-service dashboard that shows you “here's what you're paying per seat, here's how many seats are actually being used.” There's no built-in cost-per-user report. Usage data is spread across LoginHistory (capped at 6 months), the User object, UserLicense, and PermissionSetLicenseAssign — four different objects you have to query and join yourself.
Meanwhile, provisioning a seat is a 10-second admin task. Deprovisioning requires a process: deactivate the user, reassign their records, clean up their queue memberships. Easy in, hard out. The result is that most orgs accumulate 15–25% of seats that haven't been touched in 90+ days.
Salesforce knows this. It's not accidental.
The four buckets of license waste
1. Inactive users holding paid licenses
The most common form of waste. Users who left the company, moved to a different system, or just stopped using Salesforce — but whose licenses were never reclaimed.
The right signal isn't LastLoginDate on the User object. That field only reflects interactive login sessions and doesn't update when a user is accessed via API or integration. The right signal is LoginHistory — specifically, the absence of a record for that user in the past 60 or 90 days.
A user with no LoginHistory records in 90 days, who was provisioned more than 30 days ago, is a candidate for deactivation. That's one license recovered per user.
At Salesforce's current list price of $165/user/month for Enterprise, each recovered seat is $1,980/year.
2. Over-licensed user types
Not every user needs a full Salesforce Enterprise or Unlimited license. Salesforce offers lower-cost license types for specific use cases:
- Salesforce Platform ($25/user/month list) — for users who only need custom app access, not core Sales Cloud or Service Cloud
- Sales Cloud Einstein add-on vs full Einstein license — many companies buy the bundle when specific features would cost less
- Experience Cloud (formerly Community) licenses — for external users, partners, and customers who don't need internal access
- Chatter Free ($0) — for users who only need to view and comment, not take action
Run a query across your UserLicense and Profile objects to see how many users are on each license type. Then ask: does their actual usage justify a full Enterprise or Unlimited seat? Pull their LoginHistory and see what objects they actually touched. Users who only access one or two objects are often good candidates for a Platform license downgrade.
3. Unused Permission Set Licenses (PSLs)
PSLs are easy to forget because they sit one layer below the main license count. Salesforce sells them as add-ons — Einstein Analytics Plus, Revenue Intelligence, Sales Engagement — at $50–$150/user/month on top of the base license.
The waste pattern: PSLs get assigned when a feature is rolled out, then the feature doesn't get adopted, and nobody reclaims the assignment. Query PermissionSetLicenseAssign joined against LoginHistory and you'll typically find 30–40% of PSLs assigned to users who never used the feature they were assigned for.
A single Einstein Analytics Plus PSL at $75/user/month, unreclaimed across 20 users, is $18,000/year in waste.
4. Integration users holding human licenses
Service accounts — the Salesforce users your integrations authenticate as — should be on Integration User licenses or, if they need API-only access, on the correct license type for their actual usage. The problem is that when integrations are set up quickly (middleware, ETL tools, Zapier, MuleSoft), someone provisions a full Enterprise user for the service account because that's the license type they know.
Beyond the cost (same $165/month as a human user), integration users holding Enterprise licenses are a security risk: they have interactive login capabilities they don't need. Check for users with Profile.UserType = 'Standard' who have recent API activity but no interactive LoginHistory. Those are your misclassified integration accounts.
How to audit each bucket
You'll need SOQL access (Developer Console, Workbench, or a connected app with api scope). Here are the baseline queries:
Inactive users (no login in 90 days)
SELECT Id, Name, Username, Profile.Name, UserType,
LastLoginDate, CreatedDate
FROM User
WHERE IsActive = true
AND UserType = 'Standard'
AND Id NOT IN (
SELECT UserId FROM LoginHistory
WHERE LoginTime > LAST_N_DAYS:90
)
AND CreatedDate < LAST_N_DAYS:30PSLs assigned to inactive users
SELECT PermissionSetLicense.DeveloperName,
Assignee.Name, Assignee.LastLoginDate
FROM PermissionSetLicenseAssign
WHERE Assignee.IsActive = true
AND Assignee.LastLoginDate < LAST_N_DAYS:90Integration users with full licenses
SELECT Id, Name, Username, Profile.UserType,
Profile.Name, LastLoginDate
FROM User
WHERE IsActive = true
AND Profile.UserType = 'Standard'
AND Username LIKE '%integration%'
OR Username LIKE '%api%'
OR Username LIKE '%service%'These queries give you the raw data. The work is in interpreting it: confirming with managers that specific users are genuinely inactive, getting sign-off before deactivating, and documenting the license count reduction you can bring to renewal.
The negotiation play
The best time to have this data is 90 days before your renewal date, not 10 days. Here's why: if you find 25 inactive seats and document it, you have three options:
- Reduce your seat count at renewal — the clean outcome. You come to the table and say: we've audited usage, we're renewing at X seats, not Y. Here's the data.
- Negotiate against the waste — if the AE won't reduce seats (sometimes there are contractual minimums), use the evidence to negotiate a flat renewal price or a discount that reflects the actual active user count.
- Reclaim and redeploy — deactivate the inactive users, reclaim the licenses, and reprovision them for new hires. You grow your team without buying new seats.
In all three scenarios, the data wins. Without it, you're negotiating on vibes. With it, you're negotiating on facts.
What to do with the data once you have it
The findings are only useful if they're in a format your CFO, procurement lead, and AE can read. A SOQL query result in a Developer Console tab doesn't travel well. What you need is a document that shows:
- Total active seats vs. purchased seats
- Inactive users by category (never logged in, inactive 60d, inactive 90d)
- PSLs assigned to inactive users (with estimated annual cost)
- Integration users on wrong license type
- Estimated annual savings at list price
That document, sent to your AE 90 days out, changes the conversation entirely. You're not a customer asking for a discount. You're a customer presenting evidence that the current contract doesn't reflect actual consumption — and you expect the renewal to fix that.
How often should you run this audit?
Quarterly is ideal. Monthly if you have high headcount churn. The worst thing is waiting until 30 days before renewal to discover you've been paying for 40 inactive users for the past 18 months. At $165/user/month, that's $118,800 paid for seats nobody used.
A quarterly audit also gives you the trend data that matters most: are you actually growing active usage, or is the usage flat while the headcount grows? That trend is what justifies or challenges the AE's “you're growing, you need more seats” argument at renewal time.
Get your license audit automatically
SpendReady connects to your Salesforce org via read-only OAuth, runs the inactive user, PSL waste, and integration user audit automatically, and delivers a weekly report to your inbox — so you have the data 90 days before renewal, not 10.
Run your first audit free →