Moving from Profiles to Permission Sets (Without Losing Your Mind)
If you've been paying attention to Salesforce's roadmap, you know that profiles are on their way out — at least for object and field permissions. The platform is moving toward permission sets and permission set groups as the primary security model. I did this migration at a state government agency across an org with 25+ profiles and hundreds of users, and I want to share what I learned.
Why Bother?
Let's start with the honest question. If profiles still work, why go through the pain?
Three reasons. First, Salesforce is going to force the issue eventually. Enhanced profiles are already deprecated in some contexts, and the writing is on the wall. Second, permission sets are genuinely more flexible — you can compose access rather than duplicating it across profiles. Third, and this was the big one for us, permission set groups with muting sets give you a level of control that profiles never could.
We had 25+ profiles because every time a team needed slightly different access, someone cloned a profile. Over the years that turned into a spreadsheet nobody trusted, with permission drift across profiles that were supposed to be identical. Sound familiar?
The Layered Model
The approach I use is a three-layer permission set model: Base, Function, and Exception.
The Base layer is one or two permission sets that every user in the org gets. This covers the bare minimum — access to standard tabs, read access to common objects, basic app visibility. Think of it as what a brand-new employee needs on day one to log in and not see an empty screen.
The Function layer is where role-specific access lives. A "Service Agent" permission set grants access to Case, Knowledge, Entitlements, and the Service Console app. A "Sales User" permission set grants Opportunity, Lead, Quote, and the Sales app. These are composable — if someone works across both sales and service, they get both permission sets.
The Exception layer is for one-off elevated access. Maybe a team lead needs delete permission on a specific object, or a data steward needs edit access to a field that's normally read-only. These are small, named, and time-bound where possible.
Permission Set Groups Are the Key
Permission set groups are what make this model practical. Instead of assigning five individual permission sets to every service agent, you create a "Service Agent" permission set group that bundles the base set, the service function set, and any standard exceptions together. One assignment per user, clean and auditable.
But the real power is muting sets. A muting set inside a permission set group lets you revoke specific permissions that would otherwise be granted by the included sets. This is huge.
Example: your Service Agent function set grants edit access to the Case object. But for a specific team that should only have read access to Cases from other business units, you add a muting set to their permission set group that revokes edit on Case. The same base permission sets, different effective access. No duplication.
The Migration Process
Here's the step-by-step I followed. First, I exported every profile's effective permissions using a combination of the Metadata API and a spreadsheet. Salesforce doesn't make this easy — you need to pull the profile XML and parse out object permissions, field permissions, tab settings, app assignments, and so on.
Then I grouped the permissions into the three layers. This was the hardest part. It required sitting down with business stakeholders and asking: what does a service agent actually need versus what they happen to have? There's always a gap between intended access and actual access that's accumulated over years of ad-hoc changes.
Next, I built the permission sets and permission set groups in a sandbox. I kept the profiles in place but stripped them down to the absolute minimum — login hours, IP restrictions, page layout assignments (which still require profiles), and record type defaults. Everything else moved to permission sets.
Then came testing. I assigned the new permission set groups alongside the stripped-down profiles and had real users test their workflows. This is where you find the gaps. Someone can't see a tab they need. Someone lost access to a report folder. Someone's Visualforce page breaks because it was checking profile name in Apex (don't do this, but it happens).
The Gotchas
Page layout assignments still require profiles. There's no way around this as of now. So you'll still need profiles — they just become very thin containers for layouts and record type defaults.
Login IP ranges and login hours are profile-only as well. If you're using these for security, the profile still has a role to play.
Record type defaults are surprisingly tricky. The default record type for a user is determined by a combination of profile and permission set, and the precedence rules aren't intuitive. Test this carefully.
If anyone in the codebase is checking UserInfo.getProfileId() or doing logic based on profile names, you need to refactor that. I found three places in our org where Apex code was branching on profile name. Replace it with custom permissions — create a custom permission, include it in the relevant permission set, and check FeatureManagement.checkPermission() instead.
What I'd Do Differently
I'd start the stakeholder conversations earlier. The technical migration isn't that hard — it's getting business owners to agree on what access each role should actually have that takes the time. If I did it again, I'd block out two weeks just for access requirement workshops before touching any metadata.
I'd also invest in automation for permission analysis from the start. I wrote scripts partway through the project to compare effective permissions between the old profile model and the new permission set model. If I'd had those from day one, the testing cycle would have been shorter.
Overall, the migration took about three months for our org — not because the work was massive, but because we did it carefully alongside normal delivery. If you're thinking about it, start now. It's one of those things that only gets harder the longer you wait.
Liked this?
Get one Salesforce insight per week. No spam.
You might also like
How AI Changes the Salesforce Consulting Model
The economic shifts AI is bringing to Salesforce consulting — what's getting cheaper, what's getting more valuable, and what the agency model looks like now.
Read →15 Years on Salesforce: What I'd Tell My Day-1 Self
Fifteen years of Salesforce, ten orgs, three major platforms shifts, and a long list of mistakes. The lessons I'd pass back to the version of me who started in 2010.
Read →SOQL Patterns That Won't Kill Your Governor Limits
The SOQL antipatterns I keep finding in code review, the patterns that replace them, and the trade-offs nobody explains — from years of production Salesforce.
Read →