Your org isn't uniquely messy. Every company running Google Workspace, Slack, Freshservice, and Intune across a mix of employees and contractors ends up with the same problem: accounts that should have been deprovisioned months ago still showing up as active, paying seats.
The contractor who finished their engagement in January and was offboarded from HR but not from Slack. The employee who transferred to a team that doesn't use Freshservice but whose license was never reclaimed. The account that's technically active because no one has touched the deactivation workflow — and so you're paying $20 a month for a user who hasn't logged in since Q3.
This is common enough that there's a name for it — entitlement entropy — and a product category built specifically to solve it. Before you finish building the custom API tool, it's worth knowing what already exists.
Why Manual Audits and Custom Scripts Don't Scale
The manual audit approach — pull user lists from each app admin console, compare against HR records, flag the gaps — works once and stays accurate for about two weeks. By the time you finish the spreadsheet, the data at the top is already wrong. One commenter in this thread described it accurately: the zombie seats that actually cost you are in the long-tail apps nobody's checking, and most teams end up with a spreadsheet that's already wrong by the time they finish it.
Custom API scripts are a step up. Hook into the Google Workspace API, the Slack API, and Freshservice's API, pull last-login timestamps, compare against a 30-day inactivity threshold, output the flagged accounts. This works well for the apps with good APIs and is the right instinct for a sysadmin who wants to solve the problem without buying another tool.
The ceiling appears at the long tail. Slack has a great API. Google Workspace has a great API. The 40-plus other applications most organizations run are where the script approach breaks down — apps with limited API access, apps that don't expose activity data, apps where the only way to see who's active is to log into the admin console manually. Building and maintaining custom integrations for each of those is the maintenance burden that turns a useful script into a full-time project.
The deeper problem is that the custom script flags the zombie accounts but doesn't reclaim them. You still have to manually revoke each license, notify each user, and track which ones were cleaned up. The flagging is the easy part. The workflow that actually closes the loop — notifies the user, waits for a response, and revokes the license automatically if there's no reply — is where the real time savings come from.
How Dedicated SaaS Management Platforms Handle Zombie Accounts
The product category the OP is looking for is SaaS Management, sometimes combined with IGA. Platforms in this category maintain direct integrations with the applications you're already using — not custom scripts you maintain, but vendor-maintained connectors — and layer optimization workflows on top.
Zluri's Continuous Optimization module handles the zombie account problem through a specific set of automated workflows.
Categorizing inactive accounts automatically. Rather than running a manual export, Zluri continuously tracks usage data across connected applications — actual logins, feature usage, activity signals — and flags accounts that fall into specific optimization categories: unused (no login in the last 30, 60, or 90 days), underused (activity below a defined threshold), and undeprovisioned (user no longer exists in the HRMS but still holds an active license). The last category is exactly the ex-contractor problem — accounts that should have been cleaned up during offboarding but weren't, now showing up as paid seats with no active user behind them.
Calculating wasted spend automatically. For each flagged account, Zluri multiplies the inactive license count by the contract's cost per seat to generate real-time estimates of wasted spend, potential savings, and realized savings after reclamation. This is the output the OP's lightweight tool aims to produce — except it runs continuously across all connected apps rather than on demand for specific applications.
Automating the reclamation workflow. When Zluri flags an unused license, it can trigger a "Request to Forego" workflow automatically. The user receives a Slack message or email asking whether they still need the tool. If they click to forego, Zluri immediately executes the license revocation via API. If they don't respond within a defined window — days, a week, whatever threshold you configure — Zluri treats the non-response as a forfeit and revokes the license automatically without requiring an IT ticket or manual intervention.
This closes the loop that manual audits and custom scripts leave open: the flagging happens automatically, the user notification is automated, and the reclamation executes without IT involvement for the standard case.
Handling the Accounts Outside Your IdP
One commenter in this thread pointed to the specific category that's hardest to manage: users not in your IdP — contractors, special users, external collaborators — who exist in downstream apps but aren't connected to the identity layer that would normally catch them at offboarding.
For this category, access reviews are the standard approach. Zluri's access certification workflows generate periodic review campaigns where app owners or managers are asked to confirm that each user's access is still appropriate. For contractors who finished their engagement, the review surfaces them as candidates for removal without requiring IT to know exactly when each contract ended.
The discovery layer helps here too: Zluri's Discovery Engine maps accounts across connected applications regardless of whether those accounts were formally provisioned through SSO. An ex-contractor whose Slack account exists independently of your Okta configuration still shows up in the discovery scan, gets flagged as undeprovisioned, and enters the reclamation workflow.
Build vs. Adopt: The Honest Calculation
The custom script approach is worth building if your app stack is small, the APIs you need are well-documented, and you want full control over the logic. For five applications with good APIs and a stable user base, a Python script that flags 30-day inactivity and calculates wasted spend is entirely reasonable and probably faster to ship than evaluating platforms.
The case for adopting a platform gets stronger as the app count grows past the range where custom API maintenance is sustainable, as the contractor and ex-employee category becomes significant, and as the reclamation workflow needs to run automatically rather than generating a list that someone has to act on manually. At 750,000 employees — the OP's scale — the custom script option is essentially off the table, and the question is which platform handles the breadth of integrations and the automation depth required.
Frequently Asked Questions
What are zombie SaaS accounts and why do they cost money?
Zombie SaaS accounts are active, licensed user accounts where the underlying user is no longer active — ex-employees who were offboarded from HR but not from downstream apps, contractors whose engagement ended without a formal deprovisioning step, or users who stopped using a tool but whose license was never reclaimed. Because most SaaS tools charge per active seat, these accounts continue to generate billing even when no one is using them. At scale, the accumulated cost of zombie accounts across a typical SaaS stack is significant.
How do you find inactive users still paying for SaaS licenses?
The reliable approach is connecting each application to a platform that tracks actual usage data — last login, feature activity, session frequency — rather than relying on manual admin console checks. SaaS management platforms like Zluri continuously monitor connected applications and automatically flag accounts that haven't shown activity within a defined threshold (30, 60, or 90 days), generating a real-time view of unused and underused licenses without manual audits.
How do you automate SaaS license reclamation for inactive users?
Automated reclamation requires a workflow that identifies the inactive account, notifies the user, and revokes the license based on their response or non-response. Zluri's "Request to Forego" workflow sends a Slack or email prompt to the inactive user, revokes the license immediately if they confirm they no longer need it, and revokes automatically after a configurable non-response window. This eliminates the manual step of acting on each flagged account individually.
How do you catch ex-contractors and ex-employees still holding SaaS licenses after offboarding?
These accounts appear when offboarding doesn't cover the full application footprint — typically when an SSO-based offboarding misses apps the contractor used independently of the IdP. A discovery layer that scans application accounts regardless of SSO connection will surface these accounts. Periodic access review campaigns where app owners confirm each user's continued need for access also catch accounts that predate the current offboarding process.
Stop Paying for Zombie Accounts
If you've started building a custom script to flag zombie accounts and calculate wasted spend, see what Zluri's Continuous Optimization module covers out of the box — including the reclamation workflow that closes the loop your script leaves open — before investing more time in the build.












