I've created a script that checks delegated and application permissions for users in Microsoft Graph, but it's running extremely slowly. Although it works fine, it takes forever to execute for all users, and I've tried various optimization techniques but haven't had much luck. I even considered rewriting it in C# since the goal is to automate the process to run regularly against tens of thousands of users and I'd like to avoid it taking days to finish. I'd love any suggestions on how to improve its performance!
5 Answers
To get your script running faster, try batching your API calls. Instead of retrieving each user individually with separate calls, you can get them all at once and store that information in a list to reuse later. For example, gather all the service principals in one go before processing them. It will save a lot of time!
Finally, have you checked if `Write-Progress` is causing your script to slow down? It can add significant overhead if not handled properly. You might want to remove it entirely or limit how often it's called to lessen its impact on performance!
Actually, I should clarify that the progress code isn’t part of the actual script I'm running. It was solely for debugging purposes. The version that runs as a service principal is still sluggish!
You might be able to speed things up by eliminating the call to `Get-MgUser` for each individual user. Collect all the permissions and applications in bulk using fewer API calls to make your script more efficient. Give this code a try:
```powershell
$grants = Get-MgOauth2PermissionGrant
$apps = Get-MgServicePrincipal -All
```
This should help you avoid the delays you’re currently facing!
Wow, that looks super efficient! I'll definitely try that next time I'm working on this script.
Just make sure you do a bit of error handling for when the app list is large; it will be worth the added complexity!
If you're facing timeouts or bottlenecks, consider implementing a retry logic with a backoff period, so that you can manage failed calls better without crashing your script. It might look something like this:
```powershell
$maxtry = 3
$Permissions = $null
while (-not $Permissions -and $maxtry -gt 0) {
try {
$Permissions = Invoke-MgGraphRequest ...
} catch {
Start-Sleep -Milliseconds 500
}
$maxtry--
}
```
This way, your script can be more resilient to temporary failures.
Thanks for the detailed example! I usually wouldn't bother with retries, but it sounds like this can really help.
You could also optimize by caching the results from your previous API calls instead of hitting the server for the same data over and over again. This will greatly reduce the number of requests you need to make during execution. For example, keep the results of `Get-MgServicePrincipal` and use them whenever needed instead of calling it multiple times.
This is such a smart idea! Caching data can really speed things up. Thanks for the tip!
Also, consider removing the progress bar as it can significantly slow down your script!