A SharePoint metadata naming convention is just a consistent, structured way of labeling fields — ProjectName_StartDate instead of Start, DocType_Invoice instead of Type. It sounds minor until you’re six months into a growing SharePoint environment and every library names things differently.
In this post: Why it matters · The naming rules · The gotcha: internal names vs. display names · Actually controlling the internal name · Migrating a column that already got it wrong · When would you actually use this? · Related reading
Why it matters
- Consistency across sites — without a convention, the same concept ends up named
DepartmentNamein one library andDeptin another, breaking reusable reports and solutions. - Better search and filtering — consistent names like
Invoice_Dateeverywhere let you build real search refiners instead of hand-tuning queries per library. - Governance that actually targets the right content — retention policies and access audits key off metadata;
DocType_ContractorDept_HRtagged consistently means policies apply where intended, not inconsistently. - Automation that doesn’t break per-library — Power Automate flows and PowerShell scripts referencing the same field names work across libraries without per-list modification.
- Easier migrations later — moving on-prem to online, or integrating external systems, is smoother when metadata isn’t a mess to begin with.
The naming rules
- Be specific, not generic:
Contract_StartDate,Invoice_Amount,Employee_HireDate— notDateorStatus. - Prefix by domain:
Proj_Title/Proj_Status,HR_EmployeeID,Fin_InvoiceNum— groups related fields and makes ownership obvious at a glance. - PascalCase or camelCase, no spaces or special characters — avoids breakage in PowerShell and REST API queries, and Power Automate actions that reference the field by name.
- Keep names concise — SharePoint caps internal field names at 255 characters, but long names get truncated or unwieldy in scripts well before that limit.
- Suffix by type:
_Date(Contract_StartDate),_Count(File_Count),_Flag(Is_ActiveFlag) — tells you what you’re working with without opening the field settings. - Standardize abbreviations once, org-wide:
Dept,Mgr,Loc— and don’t let individual site owners invent their own.
Field names that vary across sites — DepartmentName here, Dept there — are exactly what breaks reusable reports and automation later.
The gotcha: internal names vs. display names
This is the reason getting the convention right before creating the column matters more than it seems like it should. SharePoint locks a column’s internal name the moment you create it, generated from whatever you typed as the display name at that moment — spaces get replaced with _x0020_-style encoding, and it’s what PowerShell, the REST API, and CAML queries actually reference under the hood. You can rename the display name freely afterward (what users see in the list view and forms), and it will look renamed everywhere in the UI — but the internal name stays exactly as it was generated the first time, permanently, with no supported way to change it after the fact. Create a column called “Start Date,” rename the display label to “Contract_StartDate” a week later to match your new convention, and every script or Power Automate flow referencing the field still has to use the original, ugly internal name (Start_x0020_Date) forever. The only real fix once this happens is deleting and recreating the column — which means re-tagging every item that used it. Get the internal name right on day one; the display name is the only one you can safely change later.
Actually controlling the internal name
“Get the internal name right on day one” is easy to say and hard to actually guarantee through the SharePoint UI, since the internal name is auto-generated from whatever’s typed into the display name box at creation time — type “Start Date” with a space, and the internal name locks in as the ugly Start_x0020_Date shown above, permanently, regardless of what the display name gets changed to later. The real fix is not typing the display name and hoping the encoding comes out clean — it’s setting the internal name explicitly, decoupled from whatever the display name says:
Connect-PnPOnline -Url "https://yourtenant.sharepoint.com/sites/yoursite" -Interactive
Add-PnPField -DisplayName "Contract Start Date" -InternalName "Contract_StartDate" `
-Type DateTime -Group "Contract Columns"
-InternalName is set explicitly here, completely independent of the human-readable -DisplayName — no spaces to auto-encode, no guessing what SharePoint will generate. This is the actual enforcement mechanism for the naming convention this post describes: scripting column creation with an explicit internal name means the convention can’t drift from what someone typed into a text box under time pressure, which is exactly how naming conventions erode in practice.
Migrating a column that already got it wrong
“The only real fix is deleting and recreating the column” from the gotcha section above is true, but leaves out the part that actually matters — what happens to the data that’s already in it. Deleting a column with existing values deletes those values too, so the fix isn’t just delete-then-recreate, it’s a real migration with an explicit copy step in between:
Connect-PnPOnline -Url "https://yourtenant.sharepoint.com/sites/yoursite" -Interactive
# 1. Add the new, correctly-named column alongside the old one
Add-PnPField -DisplayName "Contract Start Date" -InternalName "Contract_StartDate" -Type DateTime -Group "Contract Columns" -AddToDefaultView
# 2. Copy every item's value from the old field to the new one
$items = Get-PnPListItem -List "Contracts" -PageSize 500
foreach ($item in $items) {
$oldValue = $item.FieldValues["Start_x0020_Date"]
if ($oldValue) {
Set-PnPListItem -List "Contracts" -Identity $item.Id -Values @{ "Contract_StartDate" = $oldValue }
}
}
# 3. Only after confirming the copy worked -- remove the old field
Remove-PnPField -List "Contracts" -Identity "Start_x0020_Date" -Force
Step 3 is deliberately separated and manual rather than folded into the same script — spot-check a handful of items against both columns first, since there’s no undo once the old field and its version history are gone. If the list has an associated view, report, or Power Automate flow referencing the old internal name, those need updating to the new one too; the migration script above fixes the data, not everything downstream that was built assuming the old name.
When would you actually use this?
- You’re standing up SharePoint for a new department and want to avoid the mess that shows up 6 months in — set the convention before the first library gets created, not after.
- A Power Automate flow keeps breaking when applied to a “similar” library — the field names weren’t actually consistent, they just looked similar.
- You’re planning a migration or integration and need metadata that maps cleanly instead of requiring a translation layer.
Related reading
- SharePoint Metadata: What You Need to Know — the broader metadata concepts this naming convention guide builds on.
That’s a wrap on this tip — comment below if you have questions.
App Catalog Authentication Automation Backup Compliance Content Type CSS Flows Google Javascript Limitations List Metadata MFA Microsoft Node NodeJs O365 OneDrive Permissions PnP PnPJS Policy PowerApps Power Automate PowerAutomate PowerPlatform PowerShell React ReactJs Rest API Rest Endpoint Security Send an HTTP Request to SharePoint SharePoint SharePoint List SharePoint Modern SharePoint Online SPFX SPO Sync Tags Teams Termstore Versioning


