Sharing rules vs profiles vs permission sets: getting the model right before it gets complicated

Written by

in

Every Salesforce org I’ve walked into with a messy security model has the same root cause. Someone conflated three different jobs, object permissions, record visibility and user-specific access, and tried to solve all three with one tool. Usually that tool is profiles, cloned a dozen times until nobody remembers which one does what.

Three separate questions, one confused answer

Profiles, permission sets, sharing rules and role hierarchy sound like they’re competing for the same job. They’re not. Each one answers a different question, and the mess starts the moment you use one to answer a question it wasn’t built for.

Profiles answer: what can this type of user do, by default, everywhere? Object-level CRUD, field-level security, login hours, session settings, page layout assignment. One profile per genuinely distinct user type. Not one per exception.

Permission sets answer a narrower question: what does this specific user, or this specific group, need on top of their baseline? A support agent who also approves refunds. A team lead who needs bulk export rights the rest of the team doesn’t. Give them a permission set. Don’t clone the profile.

Sharing rules, org-wide defaults and role hierarchy answer something else entirely: which records can this user see, given what they’re already allowed to do to that object type? Object access and record access are not the same job, and treating them as interchangeable is where I see the most damage on a live org.

Why profile cloning gets out of hand

I’ve inherited an org with 40-odd profiles for around 200 users. Every time someone needed one extra permission, the fix was clone the profile, tweak it, assign it. Two years in, nobody could say with confidence what “Sales Rep – APAC – Senior – v3” granted versus “Sales Rep – APAC – Senior – v3 (copy)”. Field-level security had drifted between them. Page layouts were out of sync. Every release turned into an audit exercise before anyone felt confident nothing had broken.

The fix isn’t clever. It’s discipline: profiles map to genuinely distinct baseline roles in the business, and stay few. Everything incremental goes through permission sets instead. If you’re cloning a profile to add one field permission, you’ve picked the wrong tool.

Permission sets are the right unit of change

Permission sets work because they’re additive and composable. A user can hold a baseline profile plus five permission sets, and you can reason about each one on its own. Revoke one without touching the others. Assign one to twelve people without cloning anything.

Bundling with permission set groups

Permission set groups start to matter once you’re past a handful of permission sets per user. Bundle “Refund Approver” and “Escalation Handler” into a group named something the business actually recognises, assign the group, and stop making admins remember which five permission sets a senior agent needs. Muting permissions within a group is worth knowing too: you can include a permission set in a group and still switch off one specific permission from it. That’s the cleanest way to handle an “almost, but not quite” case without another clone.

Sharing rules aren’t a patch for object permissions

This is the mistake that costs the most later. A user can’t see records they should see, so someone writes a sharing rule to fix it, without checking whether the actual gap is object or field-level access. Sharing rules only grant additional record visibility on top of what the object permissions already allow. If the profile or permission set doesn’t grant Read on the object in the first place, no sharing rule will ever fix that. I’ve watched a team burn most of a day debugging a sharing rule that was never going to work, because the real problem sat one layer down.

Start with org-wide defaults set as restrictively as the business genuinely needs, usually Private or Controlled by Parent for anything sensitive. Let role hierarchy handle the natural case: a manager sees their team’s records because that’s how the org actually works. Reach for sharing rules only for the exceptions role hierarchy can’t express, ownership-based or criteria-based visibility across teams that don’t share a reporting line. Treat manual sharing as what it is: a one-off, temporary exception, not a standing part of your access model. If you’re explaining a business rule through a dozen manual shares, you’ve actually found a sharing rule or a public group you haven’t built yet.

A framework that holds up under pressure

When a new access requirement lands, I ask it in this order.

  • Is this about what a user can do to a record type, or which records of that type they can see? Object permission versus record visibility, decide which one you’re actually solving before you touch anything.
  • If it’s object permission: does every user with this profile need it, or just some? A baseline change to the profile, or a permission set for the subset.
  • If it’s record visibility: does the role hierarchy already express this relationship? If yes, you’re probably done once org-wide defaults are set correctly. If no, is it consistent and rule-based, or a genuine one-off?
  • Rule-based exceptions become sharing rules or public groups. One-offs become manual shares, and get reviewed later, not left forever.

None of this is exotic. It’s the same four questions on every project, and the orgs that stay clean are the ones where someone asked them before the first permission set existed, not two years and forty profiles later. That 40-profile org took three sprints to unwind safely, mapping every user to what they actually needed rather than what their historical profile happened to grant. Getting the model right up front costs an afternoon of discipline. Getting it wrong costs a migration project.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *