SharePoint / Guide 3

SharePoint Online tips

PnP.PowerShell and the SPO module in practice: paging, batching, sharing, recovery, storage.

1. Two modules, two jobs

Use the SPO module (Connect-SPOService) for tenant and site-collection settings: sharing, storage, lock state, hub sites, deleted sites. Use PnP.PowerShell (Connect-PnPOnline) for anything inside a site: lists, files, permissions, pages, provisioning. Trying to do content work with the SPO module is the most common dead end.

Connect-SPOService -Url https://sharepointonline-admin.ravindran.in
Connect-PnPOnline -Url https://sharepointonline.ravindran.in/sites/HR -ClientId $env:PNP_CLIENT_ID -Interactive

2. Page through big lists

Get-PnPListItem -List "Documents" -PageSize 500 -Fields FileRef, Modified

Without -PageSize, a large list will fail on the 5,000 list view threshold. In SharePoint Online that threshold can't be changed, even though a list can hold millions of items. Indexed columns and paging are how you work with it.

3. Batch your writes

Adding or updating thousands of items one call at a time is slow and gets throttled. Batch them:

$batch = New-PnPBatch
foreach ($row in Import-Csv .\items.csv) {
    Add-PnPListItem -List "Assets" -Values @{ Title = $row.Title; Location = $row.Location } -Batch $batch
}
Invoke-PnPBatch -Batch $batch

4. Respect throttling

HTTP 429 and 503 responses mean you're being throttled. PnP.PowerShell retries automatically, but you can help: run heavy jobs outside business hours, avoid running many parallel sessions against the same site, and use search or Graph for read-only reporting instead of crawling every item.

5. Use search for fast tenant-wide reports

Search indexes almost everything already. It's often the fastest way to answer "where is X":

Submit-PnPSearchQuery -Query "contentclass:STS_Site" -All -SelectProperties Title, Path, LastModifiedTime
Submit-PnPSearchQuery -Query "filetype:pst OR filetype:iso" -All

6. Force a re-crawl after schema changes

Changed a managed property mapping or column? Request a reindex instead of waiting:

Request-PnPReIndexList -Identity "Contracts"
Request-PnPReIndexWeb

7. Restore deleted sites (within 93 days)

Get-SPODeletedSite
Restore-SPODeletedSite -Identity https://sharepointonline.ravindran.in/sites/OldProject

For a user who deleted hundreds of files by mistake (or a sync client gone wrong), see Restore-SPORecycleBinByUser.ps1.

8. Control sharing per site

Tenant settings are the ceiling; each site can be more restrictive:

Set-SPOSite -Identity https://sharepointonline.ravindran.in/sites/Legal -SharingCapability ExistingExternalUserSharingOnly
# Disabled | ExistingExternalUserSharingOnly | ExternalUserSharingOnly | ExternalUserAndGuestSharing

Run Get-SPOSiteInventory.ps1 to see which sites allow "Anyone" links.

9. Get storage back from version history

Versions of large files (videos, CAD, big Excel models) quietly consume a lot of tenant storage. Options, from least to most hands-on:

  • Newer SPO module versions support automatic version trimming at tenant or site level (EnableAutoExpirationVersionTrim on Set-SPOTenant / Set-SPOSite) and site-level batch delete jobs (New-SPOSiteFileVersionBatchDeleteJob). Check Get-Help on your installed module version for the exact parameters.
  • For a single library, use Remove-SPOOldFileVersions.ps1 and always run it with -WhatIf first.

10. Temporarily grant yourself site collection admin

Set-SPOUser -Site https://sharepointonline.ravindran.in/sites/HR -LoginName admin@ravindran.in -IsSiteCollectionAdmin $true
# ... do the work ...
Set-SPOUser -Site https://sharepointonline.ravindran.in/sites/HR -LoginName admin@ravindran.in -IsSiteCollectionAdmin $false

Remove yourself afterwards. It's cleaner for audits and for the site owners.

11. Hub sites for navigation and branding

Register-SPOHubSite -Site https://sharepointonline.ravindran.in/sites/Intranet -Principals $null
Add-SPOHubSiteAssociation -Site https://sharepointonline.ravindran.in/sites/HR -HubSite https://sharepointonline.ravindran.in/sites/Intranet

Hubs replace most of what subsites were used for. Build flat, and connect with hubs.

12. Copy a site's structure with PnP provisioning

# From the source site
Get-PnPSiteTemplate -Out .\ProjectTemplate.xml -Handlers Lists, Fields, ContentTypes, Navigation
# On the target site
Invoke-PnPSiteTemplate -Path .\ProjectTemplate.xml
Set-SPOSite -Identity https://sharepointonline.ravindran.in/sites/Archive -LockState ReadOnly
# Unlock | ReadOnly | NoAccess

14. Custom script: enable only as long as you need it

Some legacy tasks need DenyAddAndCustomizePages turned off on a site. Turn it off, do the work, and let it go back on. Microsoft has also been tightening this setting over time, so don't build processes that depend on it staying off.

Set-SPOSite -Identity https://sharepointonline.ravindran.in/sites/Legacy -DenyAddAndCustomizePages $false