Salesforce · · 14 min read

Salesforce Security for Architects

A comprehensive guide to Salesforce security architecture — implicit sharing, roles vs territories, team sharing, data skew prevention, guest user security, and standard object sharing limitations.

Part 110: Salesforce Security for Architects

Welcome back to the Salesforce series. Security is one of those areas that every architect touches but few truly master. Most people understand the basics — profiles control object access, sharing rules extend record visibility, and the role hierarchy rolls access up. But the real complexity starts when you layer in implicit sharing, data skew, team-based access, guest user considerations, and the quirks of how standard objects behave differently from custom ones.

In this post we are going deep on the security topics that matter most at the architecture level. These are the concepts that show up in design reviews, that trip up implementations at scale, and that Salesforce expects you to understand if you are making decisions that affect an entire org.


Implicit Sharing

Most architects are comfortable with explicit sharing — sharing rules, manual shares, Apex managed shares. But implicit sharing is what catches people off guard because it happens automatically, behind the scenes, with no sharing rules to inspect.

Parent-Child Implicit Sharing

When a user owns a child record in a master-detail relationship, Salesforce grants implicit read-only access to the parent record. This makes sense if you think about it: you cannot meaningfully view an Opportunity Product without seeing the Opportunity it belongs to. The platform handles this without you writing any sharing logic.

The reverse is also true. If a user has access to a parent record in a master-detail relationship, they automatically get access to all child records. This is because master-detail children inherit the sharing settings of their parent. You cannot set OWD (Organization-Wide Defaults) independently on the detail side of a master-detail — the parent controls everything.

This means that in a master-detail model, making the parent record visible to someone gives them access to every child record under it. There is no way to hide specific detail records while exposing the parent. If your business requires that kind of selective visibility, you need a lookup relationship instead, with independent OWD settings on each object.

Portal Implicit Sharing

Portal and Experience Cloud users get implicit sharing through Account and Contact relationships. A portal user associated with an Account can see other Contacts on that Account, and depending on configuration, can see Cases and Opportunities tied to that Account. This is controlled by the sharing set and share group configurations in Experience Cloud, but the underlying mechanism is implicit — the platform grants access based on the user’s Account association without any sharing rules.

Architects need to pay attention here because portal implicit sharing can inadvertently expose data across partner organizations if multiple partners share an Account record.


Master-Detail Sharing Considerations

The master-detail relationship does more than cascade delete. It cascades sharing. The detail record has no OWD of its own. Its visibility is entirely controlled by the parent record’s sharing configuration.

This has major implications. If you set the Account OWD to Private and you have a master-detail from Account to a custom object called Project__c, then Project__c’s visibility is controlled entirely by Account sharing. You cannot make Projects more restrictive than Accounts, and you cannot make them more open unless you make Accounts more open.

The owner field on a detail record in a master-detail relationship is effectively irrelevant for sharing purposes. The record is shared based on who can see the parent, period. Reparenting a detail record (if the relationship allows it) changes who can see it, because it now inherits from a different parent’s sharing.

When designing your data model, ask yourself: does the child object always follow the parent’s visibility rules? If yes, master-detail is appropriate. If there are scenarios where child records need independent access control, use a lookup and manage sharing separately.


Roles vs Territories: When to Use Each

Both role hierarchies and territory hierarchies provide a way to structure data access. They are not interchangeable, and choosing the wrong one creates problems down the road.

Role Hierarchy

The role hierarchy is Salesforce’s primary mechanism for vertical data access. Users higher in the hierarchy can see records owned by users below them. It is a single tree structure — each user is assigned exactly one role, and that role has exactly one parent (except for the CEO/top-level role).

Roles work well when your data access model follows a strict management reporting structure. A VP of Sales sees everything their Regional Managers see, who in turn see everything their Reps see. Clean, predictable, easy to understand.

Roles break down when a user needs to see data across multiple branches of the hierarchy. If a rep sells into two regions, or a manager oversees teams in different product lines, the single-role-per-user constraint forces you into workarounds like sharing rules or manual shares.

Territory Hierarchy

Territory management solves the multi-dimensional access problem. A user can be assigned to multiple territories simultaneously, and each territory can have its own hierarchy. Territories are specifically designed for Account and Opportunity access, and they work well when your go-to-market model is territory-based rather than manager-based.

Use territories when reps are assigned accounts based on geography, industry, or named-account lists, and when those assignments overlap. Use roles when your access model aligns with your org chart and each user fits neatly into one branch.

One important consideration: territories only apply to Accounts and Opportunities (and their related objects). If you need multi-dimensional access to Cases, custom objects, or other standard objects, territories will not help — you are back to sharing rules and programmatic sharing.


Team Sharing

Salesforce offers built-in team sharing for three standard objects: Accounts, Opportunities, and Cases.

Account Teams

An Account Team is a group of users who work together on an Account. Each team member gets a defined access level (Read Only or Read/Write) on the Account, plus you can independently control their access to Opportunities and Cases related to that Account. Account Teams are useful when multiple reps, SEs, CSMs, and executives all need visibility into the same Account with different levels of access.

Opportunity Teams

Opportunity Teams work similarly but at the Opportunity level. Team members get a specified access level on the Opportunity. This is common in complex sales where an overlay rep, a solutions engineer, and a manager all need access to the deal. Opportunity Team members also get a role label (like “Sales Engineer” or “Executive Sponsor”) which is useful for reporting.

Case Teams

Case Teams are slightly different — they use predefined roles configured by an admin, and each role has a specific access level. This is handy for support scenarios where escalation engineers, product specialists, and account managers all collaborate on a Case.

From an architecture perspective, team sharing is powerful but it creates individual share records. If every Account has a team of 10 people, that is 10 share records per Account. At scale, this contributes to sharing table size and can affect performance. If you find yourself creating teams with hundreds of members, you should look at sharing rules or public groups instead.


Avoiding Data Skew

Data skew is one of the most dangerous performance problems in Salesforce, and it is directly tied to security architecture because it affects the sharing calculation engine. There are three types architects must watch for.

Account Skew

Account skew happens when a single Account has more than 10,000 child records (Contacts, Opportunities, Cases, or custom children). When someone changes sharing on that Account — say, the Account owner changes — Salesforce must recalculate sharing for every child record. With 10,000+ children, this recalculation can time out, fail, or cause severe performance degradation for the entire org.

The fix is architectural: break up mega-Accounts into sub-accounts (a parent-child Account structure), or move child records to a custom object with a lookup instead of a master-detail so they have independent sharing.

Ownership Skew

Ownership skew occurs when a single user owns more than 10,000 records of any object. This matters because the sharing table stores grants based on ownership. When the role of that user changes, or when a sharing rule references that user’s role, Salesforce must recalculate shares for every record they own.

The classic offender here is the “integration user” or “system admin” account that becomes the default owner for records created by automated processes. The solution is to distribute ownership across multiple users or use a queue as the owner for records that do not have a natural human owner.

Lookup Skew

Lookup skew happens when too many records point to a single parent through a lookup relationship. For example, if 100,000 Cases all reference the same Account via a lookup, operations on that Account can experience lock contention and performance issues.

The thresholds are not as hard as the 10,000 number for Account and Ownership skew, but as a rule of thumb, start investigating when any single record is the target of more than 10,000 lookups. Architectural remedies include distributing references across multiple parent records or batching operations that touch heavily referenced records.


Designing Guest User Security

Guest users — unauthenticated visitors to your Experience Cloud sites — are one of the most security-sensitive areas in Salesforce. After several high-profile data exposure incidents, Salesforce has tightened guest user security significantly.

Key Constraints

Guest users operate under a Guest User Profile that has extremely limited permissions. Since Spring ‘20 and subsequent releases, Salesforce has enforced several restrictions:

  • Guest users cannot own records. Any record created by a guest user is assigned to a default owner specified in the site configuration.
  • Guest users cannot be included in sharing rules, roles, or public groups (since Winter ‘21).
  • Access to records for guest users is controlled exclusively through Guest User Sharing Rules, which are a separate, more restrictive type of sharing rule.
  • Guest users cannot access records via implicit sharing or the role hierarchy.
  • The “Secure guest user record access” setting (enabled by default in newer orgs) ensures that guest users can only see records explicitly shared with them.

Architecture Recommendations

Keep the guest user footprint as small as possible. Only expose the objects and fields that the public site genuinely needs. Use a dedicated set of Apex classes running as “without sharing” (carefully!) to retrieve specific records for display, rather than relying on the guest user’s profile to have broad read access.

Never store sensitive data on objects that the guest user profile can access. If your Experience Cloud site has a public-facing FAQ object, make sure that object does not also contain internal notes or customer-specific data.

Use Apex-managed sharing if you need guest users to create records that other users will later access — since the guest user cannot own the record, the Apex trigger or flow should assign ownership to the appropriate user or queue immediately upon creation.


Designing Integration User Security

Integration users are another area where security shortcuts create long-term problems. Every external system that connects to Salesforce via API should use a dedicated integration user, not a shared admin account.

Best Practices

One integration user per system. If your ERP, marketing platform, and data warehouse all connect to Salesforce, each should have its own integration user. This gives you audit trail clarity (you know which system made which change), and it lets you tune permissions independently.

Permission Sets over Profiles. Give the integration user a minimal profile (like “Minimum Access - Salesforce” or a custom profile with almost nothing enabled) and then add specific permissions through Permission Sets. This follows the principle of least privilege and makes it easy to add or remove access as integration requirements change.

API-Only License. Use the Salesforce Integration license (or API-Only User license in older orgs) for integration users. This prevents anyone from logging into the UI with the integration credentials, reduces your license cost, and makes the user’s purpose clear.

Avoid ownership accumulation. As mentioned in the ownership skew section, integration users are the primary offenders for owning too many records. Build your integration logic so that record ownership is assigned to the appropriate business user or queue, never left on the integration user as a default.

Named Credentials. Store external system endpoints and authentication tokens in Named Credentials rather than hardcoding them in Apex or storing them in custom settings. Named Credentials are encrypted, support OAuth flows, and can be managed declaratively.


Pricebook, Product, and Price Book Entry Sharing

This is a topic that surprises even experienced architects. Pricebooks, Products, and Price Book Entries (PBEs) have unique sharing behavior that does not follow the standard OWD/sharing rule model.

Products have an OWD setting of “Use Standard Price Book” which is not the same as Public Read or Private. A user’s ability to see a Product depends on whether they can see the Price Book that contains it. You cannot write sharing rules on Products directly.

Price Books are controlled by their own OWD setting, but the critical nuance is that a user needs access to both the Price Book and the Product to see a Price Book Entry. PBE visibility is the intersection of Product access and Price Book access.

In practice, this means that if you restrict Price Book access (for example, giving each sales team its own Price Book), you are also restricting which Products those teams can add to Opportunities. This is intentional — it is how Salesforce controls pricing segmentation — but it catches architects off guard when they try to set up Product visibility independently of Price Book access.


Sharing Limitations with Standard Objects

Not all standard objects follow the same sharing model. Custom objects give you full flexibility — Private OWD, sharing rules, Apex sharing, manual shares, criteria-based sharing. Standard objects are more constrained, and each one has its own quirks.

Campaigns default to Public Read Only for users with the “Marketing User” checkbox enabled, and Full Access is not an OWD option. You can restrict Campaign access via the role hierarchy, but criteria-based sharing rules are not available.

Solutions are always Public Read Only or Public Read/Write. You cannot make them Private. This limits your ability to segment solution access across teams.

Activities (Tasks and Events) respect a “Controlled by Parent” OWD, meaning access is based on the related record (Lead, Contact, Account, Opportunity). You cannot set Activities to Private independently of their parent. Users who can see the related Account can see the Activities on it.

Knowledge articles use a different access model entirely — Data Categories and Category Visibility settings control which articles are visible to which users, independent of the standard OWD/sharing rule mechanism.

Contracts inherit sharing from their parent Account. You cannot write independent sharing rules on Contracts or set a different OWD for them.

These limitations mean that architects must understand the sharing model for every standard object they include in their design. You cannot assume that the approach that works for custom objects will work for standard ones. Always check the Salesforce sharing documentation for each standard object before committing to a design.


Wrapping Up

Security architecture in Salesforce is not just about setting OWDs and role hierarchies. It is about understanding implicit sharing, knowing when to use master-detail versus lookup based on sharing requirements, choosing between roles and territories based on your go-to-market model, and designing around data skew before it becomes a production incident.

The topics we covered here — implicit sharing, team sharing, skew prevention, guest user lockdown, integration user design, and standard object sharing quirks — are the ones that separate surface-level implementations from architecturally sound ones. If you are reviewing a Salesforce design and the architect cannot explain how guest users are secured or what happens when an Account accumulates 50,000 child records, that is a red flag.

Next up in the architecture series, we will continue exploring advanced platform topics. See you in the next post.