Platform & Architecture

Security

Who can see what: designing the Salesforce access model on purpose

Most access models were never designed. They were assembled from individual requests, each one reasonable at the time, and the result is an org that cannot explain itself.

A locksmith at his bench, the walls of the shop hung with hundreds of cut keysPlatform & Architecture

Ask any org one question: who can see this record, and why. Not who owns it. Who can see it, named, with the reason beside each name.

Very few can. That is not usually because the model was built badly. It is because it was never built at all. It was assembled, one access request at a time, over five or seven years, by several administrators who each made a reasonable decision with the information in front of them. Nobody designed the thing, so nobody can now describe it.

The consequence shows up in two places. The first is an audit, where the question is asked formally and the answer takes three people and a week. The second is an incident, where the investigation finds that no single change caused the exposure: it was the sum of four grants, each defensible on its own.

Both come from the same root. Access in Salesforce is decided by a specific sequence of mechanisms, and most organisations treat that sequence as a bag of tools rather than an order. When access is missing, they reach for whichever tool is nearest. When access is excessive, they reach for a tool that cannot restrict, and add more grants trying to remove one.

The order is the whole model

Salesforce evaluates access to a record in a defined sequence, and the sequence matters more than any individual setting inside it.

Object permissions come first, and they are binary in effect: with no read on the object, nothing further in the chain can give the user a record. Assuming they have it, organisation-wide defaults set the baseline for records the user does not own. That baseline is the most restrictive position, and it is the only part of the model whose job is to take access away.

Everything after it opens access back up. The role hierarchy grants users visibility of records owned by people below them. Sharing rules grant access to defined groups based on ownership or record criteria. Manual sharing grants access to individuals on a single record. Apex managed sharing grants access programmatically where the declarative options cannot express the requirement. Teams, territories and implicit sharing on related records do the same job in narrower circumstances. None of these can take anything away. They are additive by design, and access accumulates through them the way it does through a permission model.

Two mechanisms sit outside that additive flow. Restriction rules narrow what a user sees even where sharing would have granted it, which makes them the second genuinely restrictive tool in the platform. Scoping rules set the default set of records a user works in without changing what they are permitted to access, which is a usability control rather than a security one, and it is regularly mistaken for the opposite.

Field-level security is evaluated separately and applies regardless of all of this. A user with full access to a record still cannot read a field their field-level security denies.

Organisation-wide defaults are the only genuinely restrictive decision

Because everything downstream is additive, the organisation-wide default is the most consequential setting in the access model. It is the ceiling on how private anything can be.

Set an object to private and you have a foundation to build on. Every subsequent grant is deliberate, visible and traceable to a rule you can name. Set it to public read and you have made a decision that cannot be unmade by any amount of downstream configuration, because nothing downstream restricts.

That asymmetry is why starting open and tightening later is so much harder than the reverse. Tightening an organisation-wide default does not merely change a setting. It removes access people have been relying on, usually without knowing which access they relied on, and the platform recalculates sharing across the object. The impact is discovered by users rather than by a report, and the discovery happens on a Monday. Meanwhile every process that quietly assumed broad visibility, a dashboard, a flow, an integration, an assignment rule, stops behaving the way it did.

There is a subtler cost too. When the default is open, nobody ever writes down who needs access, because nobody has had to. So when the tightening finally happens, the requirements do not exist. They have to be reconstructed by asking, and the answers you get are what people believe they need, which is always broader than what they use.

The design question is therefore not "what does the business need to see" but "what is the smallest baseline that lets the widening mechanisms express the real rules". Where confidentiality is a regulatory obligation rather than a preference, that calculation changes again, and we have written separately about what actually changes when the org belongs to a bank.

The role hierarchy is a visibility structure, not an org chart

The most common structural mistake in a Salesforce access model is building the role hierarchy to mirror the organisation chart because the two look alike.

They are not the same object. The org chart describes reporting lines and accountability. The role hierarchy describes one thing only: who inherits visibility of whose records. Where the two happen to coincide, mirroring works. Where they diverge, mirroring produces exposure nobody intended and nobody can see.

The divergences are ordinary. A team leader who manages people but should not read their pipeline. A regional director who reports into a global function with no business reading regional customer data. A matrix arrangement where somebody has two managers and the hierarchy can only express one. A shared services function that sits above several business lines on the chart and, for information barrier reasons, must sit beside them in the data model.

The harm is compounded by inertia. Role hierarchies are rarely revisited, because changing one recalculates sharing and everybody is nervous about it. So the hierarchy built in year one, when the org chart happened to be a fair proxy, survives three reorganisations that made it a bad one.

The discipline is to treat the hierarchy as a deliberate artefact with its own justification. Every level should exist because a specific inheritance is required, not because a management layer exists. Where the answer to "why is this role above that one" is "because that is who they report to", the hierarchy is being used as documentation rather than as a control.

Sharing rules, and when they are the right answer

Sharing rules are the correct tool for a specific shape of requirement: a group of people needs access to a definable set of records, the rule can be expressed through ownership or record criteria, and the requirement is durable rather than one-off.

They are the wrong tool for three shapes they are nonetheless routinely used for.

One person, one record, once. That is manual sharing. Solving it with a criteria-based rule creates a permanent structure to serve a temporary need, and the structure outlives the need by years.

A requirement that changes constantly. If the criteria need editing every few weeks, the data model is doing the wrong job. Something that should be a field on the record is being expressed as a rule about records.

Anything that needs to restrict. Sharing rules only grant. A rule cannot exclude a subset, and attempting to build exclusion out of grants produces exactly the layering that makes an access model unreadable. Where the requirement is genuinely "these users must not see these records even though other mechanisms would allow it", restriction rules exist for that, and reaching for them early is far cheaper than discovering them late.

Apex managed sharing sits below all of this, and the honest guidance is to treat it as a last resort with a named owner. It can express rules the declarative tools cannot, which is precisely why it accumulates into the place difficult requirements go to be solved invisibly. Sharing written in code is sharing no administrator will find when they audit the sharing settings, so it needs documenting where the access review will look, not only where the developers will.

Object permissions, field permissions, and where exposure lives

Record access and field access are different questions with different answers, and the second is where most real exposure sits.

Object permissions decide what a user can do with an object at all: read, create, edit, delete, and the broader capabilities that let a user view or modify all records of a type. Those broader capabilities bypass the sharing model entirely. A user with data-wide access sits outside everything described above: the organisation-wide default does not apply to them, the hierarchy is irrelevant, and no sharing rule is doing any work. Counting the humans who hold that access is usually the fastest way to focus a leadership conversation about the model.

Field-level security is the control most orgs under-use, and the reason is a misunderstanding that is easy to hold and expensive to keep. Removing a field from a page layout feels like hiding it. It is not. It hides the field on that page, and the field remains fully available through reports, list views, search results, the API, data exports and anything built on top of them. A salary field taken off a layout is still in the report builder. A customer identifier taken off a layout is still in an export.

That gap is what makes field-level security the highest-leverage control in the model, and it is invisible twice over: nothing in the interface announces it, and a field left readable produces no error, no warning and no evidence until somebody notices it in a report.

Record types belong here for the opposite reason. They control which picklist values and layouts a user sees, and they are frequently assumed to control access. They do not. A record type is a presentation and process construct, and anything depending on one for confidentiality is depending on something that was never a security boundary.

Permission sets and permission set groups

Permission sets and permission set groups are the current recommended approach for granting permissions, and Salesforce has been steadily moving administrators away from assigning permissions directly on profiles and towards them. Permission set groups compose several sets into a single assignment that matches a job, and muting permission sets handle the exceptions without forking the group.

Profiles have not been removed and no retirement date is established, so treat this as a direction of travel rather than a completed migration, and confirm the current status of any specific capability with Salesforce directly rather than relying on second-hand summaries. Most orgs are somewhere in the middle, which means access is expressed in two places with different mental models, and answering "what can this person see" requires checking both. How that sprawl accumulates, how to measure it and how to clean it up is a subject in its own right, covered in permission set debt. This article is about the model those permissions sit inside, which has to be right before a clean-up is worth doing.

What each mechanism grants, and what it can never do

The most useful artefact for an access review is not a permission matrix. It is a statement of what each mechanism is capable of, because most misuse comes from asking a tool to do something it structurally cannot.

MechanismWhat it grantsWhat it can never restrictWhere it is checked
Organisation-wide defaultsThe baseline access to records a user does not ownAnything a downstream grant has already widenedEvery record access, before any widening
Role hierarchyVisibility of records owned below a user's roleAnything, it only inherits upwardRecord access, after the baseline
Sharing rulesAccess for groups, by ownership or record criteriaAnything, grants are additive onlyRecord access, after the hierarchy
Manual sharingAccess to one record for one user or groupAnything, and it survives until removed by handRecord access, per record
Apex managed sharingAccess expressed in code where rules cannot be declaredAnything, and it is invisible to a settings auditRecord access, at share record level
Restriction rulesNothing, it narrows what sharing grantedThe user's object permissionsRecord retrieval, after sharing
Scoping rulesNothing, it sets the default record scopeActual access, users can still reach the recordsDefault scope, not the security boundary
Object permissionsThe ability to read, create, edit or delete a typeField content, and data-wide access bypasses sharingEvery operation on the object
Field-level securityRead or edit on individual fieldsRecord visibility itselfEvery surface: UI, reports, list views, search, API
Permission sets and groupsAdditive capability, object and field accessAnything, muting sets are the exception mechanismAt assignment, composed with the profile

Read the third column first. Most access failures are an attempt to make something in that column happen anyway, expressed as more configuration.

The surfaces everybody forgets

The mechanisms above are the model. What follows is where the model gets bypassed, and these are the findings that turn up in audits, because they are the ones nobody looks at until somebody does.

Reports and dashboards that run as another user. A dashboard can be configured to run as a specified user, so every viewer sees the data through that user's access rather than their own. That is a deliberate and useful feature, and it is also a general-purpose way to publish data past the sharing model. A dashboard running as an executive shows executive-level data to anyone who can open it. Inventory these, name the running user for each, and treat that choice with the same care as any other access grant.

List views. The records inside a list view respect sharing, so a view does not leak records. What it can leak is shape. A view whose filter criteria name a sensitive field, a segmentation or a flag such as an investigation status tells the viewer that the field exists and what its values are, even where every record is filtered out. Visibility of the view definition is configured separately from the records, and almost never reviewed.

Experience Cloud external users. External access is a separate model with separate defaults, separate sharing mechanisms and a separate set of assumptions. It is also the place where a mistake is most public, because the audience is outside the organisation. The most common failure is not a misconfigured setting but an internal assumption carried across a boundary: an object, a field or a piece of content designed on the premise that only staff would ever see it. We have written about the design side of that in portals people actually finish tasks on, and the access review for an external surface should be run independently rather than inherited from the internal one.

Integration users. Almost every org has at least one user with far more access than any person, because it was built to serve several systems and each new integration added a little more, and nothing was ever removed. That user typically has broad object access, often data-wide access, and its credentials sit in configuration somewhere. Scope integration users per integration rather than per platform, review what each one actually calls, and treat any data-wide permission on an integration user as a finding that needs a written justification.

Apex that runs without sharing. Apex does not enforce the sharing model unless it is written to, and field-level security is likewise not applied automatically. That is by design, because system context is necessary for plenty of legitimate work, but it means a class, a trigger or an invocable action can read and return records the calling user could never open. Anything user-facing should enforce sharing explicitly and enforce field access explicitly, and the review question is not whether the code is correct but whether anybody decided.

Search and the API. Both respect sharing and field-level security, which is exactly why field-level security matters so much: it is the only control that covers them. A field hidden by layout is fully visible to anything that queries the object.

Access that leaves the org

Every control described so far governs what a user can see inside Salesforce. A separate question is what leaves, and it is governed by a different set of features usually owned by a different person.

Data exports, report exports and bulk extracts move data outside every control the platform enforces. Once a report is in a spreadsheet on a laptop, field-level security is a historical fact rather than a control. Treat the permissions that allow export as elevated rather than routine, and monitor the exports themselves: Event Monitoring records this kind of activity, and it is one of the few ways to answer questions about viewing and extraction rather than editing.

Connected Apps are the other exit. Each one is an authorised path into the org with its own scopes and policies, and the population grows the way permission sets do. Review the list, confirm each app is still in use, and check the permitted users policy and IP restrictions on each. Named Credentials govern the outbound direction and keep authentication details out of code. External Objects bring the question full circle, because data displayed through them lives somewhere else and is governed there.

Around all of this sit the controls deciding who gets in at all: Multi-Factor Authentication, Login IP Ranges and session settings. They are not part of the sharing model, but they bound it, and an immaculate sharing design behind weak authentication has simply moved the weakest link.

A testable definition of done

An access model is finished when the organisation can answer a small set of questions on demand, with evidence, without convening a working group. Here is the set we use, and how to check each one.

QuestionHow to check it
Who can see this record, and by which mechanism?Open the record's sharing detail and name the grant behind each entry. Anything unexplained is a finding.
Which objects are private, and where is that written down?Compare the organisation-wide default settings against the design document. A default nobody can justify is a decision nobody made.
Who can view or modify all data?Count the humans, not the profiles. The number should be small and every name justifiable.
Which fields are restricted, and on which profiles and permission sets?Run the field accessibility view for each sensitive field. Layout removal is not an answer.
Which dashboards run as another user, and who is that user?List them and name the running user for each. Treat every one as a published data grant.
What does each integration user have, and why?One written justification per integration. Data-wide access needs a reason and a review date.
Which Apex runs without enforcing sharing, and was that deliberate?Review user-facing classes for sharing and field enforcement. The finding is undecided, not incorrect.
Who can export data, and who reviewed the last exports?Check the export permissions, then check the monitoring. If nobody reviews it, nobody knows.
What can external users reach?Run the external access review separately. Never infer it from the internal one.
When was this last checked, and by whom?A named owner and a date. Without those, every answer above is a snapshot with no shelf life.

Two platform features make the list cheaper to run than it looks. Health Check measures your security settings against a standard, which is a useful starting position rather than a conclusion, and Security Center aggregates the picture where you run more than one org. Where the obligation extends to proving what happened rather than what was configured, Salesforce Shield adds Event Monitoring for activity and Field Audit Trail for retention, and both are far cheaper to enable before you need them than to explain the absence of afterwards.

None of this is exotic, and none of it requires a programme. It requires somebody to own the model as a design rather than as a queue of requests, and the ten questions above to have answers written down somewhere other than one person's memory. The orgs that can answer them did not build a more sophisticated access model. They built an ordinary one on purpose, and then kept it that way.

Sources

  1. Salesforce Trailhead: Data security and access control
  2. Salesforce Trailhead: Security basics and best practices
  3. Salesforce: Cloud data security

Common questions

Answered, directly.

The questions this piece settles about Platform & Architecture, answered in full on this page.

Object permissions decide whether the user can work with the object at all. Organisation-wide defaults then set the most restrictive baseline for records the user does not own. The role hierarchy, sharing rules, manual sharing and Apex managed sharing only widen that baseline. Restriction rules narrow the result again, and field-level security applies to every field regardless of record access.

Permission sets and permission set groups are the recommended approach, and Salesforce has been steadily moving administrators in that direction. Profiles still exist and still carry settings, so treat the migration as gradual rather than complete, and confirm the current status of any specific capability with Salesforce directly rather than relying on second-hand summaries.

Because it is the only control that follows the field everywhere. Removing a field from a page layout hides it on that page and nowhere else. The same field remains available through reports, list views, search results, data exports and the API, so a genuinely sensitive field has to be restricted through field-level security rather than through layout.

Free architect conversation

Talk to an architect, not a sales rep.

Architecture review, before it gets expensive. 60 seconds to brief us, and a certified architect replies within one business day.

What decision is actually in front of you?

Pick the closest fit. The review is free, and we will tell you to keep your current design if keeping it is right.

What does this decision touch?

Optional. Choose any that apply, or skip ahead.

Where does your org stand today?

Optional. A few sentences is plenty: what is working, what is stuck, and what you want to be true. Or skip ahead and tell us on the call.

Who should the architect reach?

A certified architect will reply to these details.

Takes about 30–60 seconds · No obligation · Architect replies within one business day

Protected by reCAPTCHA. Google's Privacy Policy and Terms apply.

More from Insights

Read by desk

Ten desks, one delivery team. Every piece is written by the people who do the work.