๐ฌ Recipe ยท Microsoft Teams
Generate a Microsoft Teams Governance Report (Inactive, Ownerless, Guest-heavy)
Audit every Team in your tenant for ownership, guest exposure, and engagement โ then flag candidates for archival, re-owning, or review.
Complexity
Intermediate
Impact
governance + security + compliance + reporting + teams + lifecycle
Context
Why This Matters
Microsoft Teams sprawl is one of the most common governance headaches in M365 tenants. Over time, Teams accumulate: owners leave the company (creating orphaned groups), external guests get invited and never removed, and project Teams outlive their purpose and sit dormant with sensitive content.
A regular Teams governance report gives IT admins a clear, data-driven view of which Teams need attention. This recipe walks you through producing that report โ enumerating every Team in the tenant, checking owner count, counting guests, and flagging Teams that match common risk patterns (orphaned, guest-heavy, low-engagement).
When to run this
- Quarterly governance review cycles
- Before a tenant migration or rename
- As part of an external-sharing audit or compliance review
- After a wave of departures (layoffs, reorgs) to catch newly orphaned Teams
Expected Outcomes
After completing this recipe you will have:
- A CSV or structured report listing every Team in the tenant with Owner count, Member count, Guest count, and a computed governance Status (Healthy / Orphaned / High Guest Count / Low Engagement).
- A Suggested Action column for each Team (e.g. Assign new owner, Review guest access, Consider archiving).
- Aggregate stats: total Teams, number orphaned, number guest-heavy, number with low engagement.
- A repeatable script you can schedule (e.g. monthly) to track governance trends over time.
Risks & Considerations
Warnings & gotchas
- This is read-only. The recipe does not archive, delete, or modify any Team. Treat the output as a decision-support tool, not an automated cleanup.
- Don't auto-archive on one signal. A Team with <3 members could be a legitimate small working group. Always confirm with the owner before archival.
- Guest thresholds are org-specific. The default "high guest count" threshold of 10 is a starting point โ tune it to your org's risk appetite.
- Inactivity needs the Reports API. Truly accurate "inactive" detection (last message posted, last channel activity) requires the
Reports.Read.Allscope and thegetTeamsActivityDetailendpoint. The basic recipe uses member count + created date as a proxy; the richer version is noted in the API section. - Privacy: Teams activity reports can contain usernames. In some jurisdictions you must anonymize before distribution โ check with your DPO.
- Throttling: Tenants with thousands of Teams will hit Graph throttling. Use paging (
$top=100with@odata.nextLink) and exponential backoff.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| Group.Read.All | Enumerate all M365 groups (including Teams), list owners, and list members. |
| Team.ReadBasic.All | Confirm a group is Teams-enabled and read basic Team properties. |
| Reports.Read.All | Optional โ required only if you want true activity data (last message, channel activity) via the Teams usage reports API. |
| User.Read.All | Resolve member userType to accurately count guests vs. internal users. |
The fastest way to get this done โ just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex CoAdmin