← Back to Security & Compliance
SEC-001 Security & Compliance 22 min read For: CTOs & Solution Architects

Salesforce Security Architecture: Profiles, Permission Sets, and Sharing Rules

The complete architectural view of Salesforce security — how profiles, permission sets, sharing rules, and field-level security interact, and where the failure points are.

VS

Vishal Sharma

Salesforce Architecture Specialist · Updated May 2026

What you will learn in this tutorial
  • Why security architecture must be designed upfront — and what it costs when it isn't
  • How Salesforce's four security layers stack, and which layer can override which
  • The profile-vs-permission-set decision: what the right architectural pattern looks like at scale
  • How org-wide defaults and the sharing model interact — and why OWD is the most consequential setting in your org
  • Field-level security at scale: the complexity explosion and how to manage it
  • When Salesforce Shield is genuinely necessary and when it's an expensive oversell
  • A pre-go-live security checklist and the ten most common enterprise misconfigurations

Why Security Architecture Is an Afterthought — Until It Isn't

In most Salesforce programmes, security gets addressed in one of two ways. Either it's treated as a configuration task — something an admin handles with profiles and permission sets during the build phase — or it's deferred entirely to a post-go-live "security review" that never materialises. Both approaches have the same outcome: a security model that was never designed, only assembled.

The cost of this is not theoretical. We've seen it play out repeatedly in large enterprise programmes. A financial services firm goes live after 18 months of build. Twelve months later, an internal audit finds that customer service representatives can see contract value fields. Not because someone deliberately granted access — because nobody deliberately restricted it. A professional services org runs for three years before realising that their role hierarchy, built for a 200-person team, is now inappropriate for a 1,400-person org across six business units. Rebuilding it post-live required a data re-architecture programme that took eight months and cost more than the original Salesforce implementation.

These are not edge cases. They are the predictable consequence of treating security as configuration rather than architecture.

The mental model shift required here is simple but important: Salesforce security is infrastructure, not configuration. The decisions you make about org-wide defaults, role hierarchy, and field-level security are foundational. Changing them post-go-live has the same disruption profile as changing your database schema mid-production. The tools are more user-friendly, but the downstream consequences are just as severe.

💡
Insight

Security design in Salesforce should happen at the same phase as data model design — not after it. Your object relationships, your OWD settings, and your sharing model are interdependent. Designing the data model without the security model produces a system where security is retrofitted around data, not built into it.

The Four Layers of Salesforce Security

Salesforce security operates in four distinct layers. They are applied in sequence, and the rule is consistent across all of them: each layer can only restrict access — it cannot grant access above what the layer above it allows. Understanding this stacking behaviour is the foundation of everything else in this tutorial.

Layer 1: Object-Level Security (Profiles and Permission Sets)

The first layer controls what objects a user can interact with at all — whether they can create, read, edit, or delete records on a given object. This is controlled by profiles and permission sets. If a user's profile does not grant Read access to the Opportunity object, that user cannot see any Opportunity records, regardless of any sharing rules that might otherwise give them access. Object-level is the entry gate: pass it, and you're into the other layers. Fail it, and everything else is irrelevant.

Layer 2: Field-Level Security

Assuming a user has object-level access, field-level security (FLS) controls which specific fields on that object they can see and edit. FLS is set per field, per profile or permission set. A sales rep might have Read access to the Opportunity object, but if their profile's FLS for Contract_Value__c is set to Hidden, they will not see that field — even though they can see the record. The field simply doesn't appear in the page layout, in reports, or in API responses.

FLS is the layer most often under-designed in enterprise programmes, and it's where the most sensitive data leakage occurs.

Layer 3: Record-Level Security (Sharing Model)

The third layer controls which specific records a user can access, given that they already have object-level access. This is where the complexity lives. Record-level security in Salesforce has four components that work in combination:

  • Org-Wide Defaults (OWD): The baseline — what every user can see by default, absent any other sharing configuration. This is the most consequential setting in this layer.
  • Role Hierarchy: Users above a record owner in the role hierarchy automatically inherit access to that owner's records, if the OWD is set to Private or Public Read Only.
  • Sharing Rules: Rule-based grants of access to groups of records, applied on top of OWD and role hierarchy. Two types: ownership-based (share all records owned by Group A with Group B) and criteria-based (share records where Region__c = 'EMEA' with the EMEA team).
  • Apex Managed Sharing: Programmatic sharing grants managed in code. Used when the business logic for sharing is too complex for declarative sharing rules.

Layer 4: System-Level Security

The fourth layer controls access to Salesforce itself — not to objects or records, but to the org. This includes IP address restrictions, login hour restrictions, multi-factor authentication enforcement, session timeout policies, and trusted IP ranges. System-level security is often managed by the IT security team rather than the Salesforce team, which creates a governance gap in many organisations. If your Salesforce team doesn't have visibility into system-level security settings, that gap should be on your risk register.

🔑
Key Concept: The Stacking Rule

Every layer can only restrict — never grant above the ceiling set by the layer above it. A sharing rule cannot give a user access to a record if their profile doesn't grant object-level access to that object. FLS cannot reveal a field to a user whose profile has the object hidden. When diagnosing access issues, always start at Layer 1 and work down. Jumping to sharing rules when the real problem is object permissions wastes hours in every org review we've ever conducted.

Profiles vs Permission Sets: The Architecture Decision

The profile-vs-permission-set question is one of the most practically consequential design decisions in Salesforce security architecture. Get it wrong at implementation and you'll spend years managing a permission model that's opaque, fragile, and expensive to change.

What Profiles Actually Are

Every Salesforce user must have exactly one profile. Profiles are the floor — they define the minimum access a user has. They control object permissions, field-level security, tab visibility, page layout assignments, record type access, login hours, and IP restrictions. Profiles are blunt instruments: every setting in a profile applies to every user who holds that profile.

The traditional Salesforce approach was to create one profile per user type: a Sales Rep profile, a Sales Manager profile, a Customer Service profile. In small orgs, this works. In large orgs, it produces profile sprawl — dozens of nearly-identical profiles with minor variations, each requiring independent maintenance when a permission change is needed across all of them.

Permission Sets: The Extension Model

Permission sets sit on top of profiles. They can only add permissions — they cannot remove them. A permission set can grant access to an additional object, enable a specific field, or add an app. Users can hold multiple permission sets simultaneously. This is the mechanism for granting targeted, additive access without creating a new profile variant.

Why "A Profile Per User Type" Is an Anti-Pattern at Scale

The moment you have more than a handful of profiles, profile management becomes a hidden cost. Consider a 500-user org with 15 profiles. You need to grant all user types access to a new custom object. That's 15 profile edits — each requiring a deployment to production if you're following change management best practices. Now consider the same org with three baseline profiles and targeted permission sets layered on top. The same change requires one permission set update.

The anti-pattern accelerates when profiles diverge over time. Two profiles that started identically, given to two slightly different user types, will diverge with every project that touches one but not the other. After three years, they're unrecognisably different, and nobody can confidently say what the difference is or whether it's intentional. This is the state of most enterprise Salesforce orgs that have been running for more than five years.

Permission Set Groups

Permission Set Groups (PSGs), introduced in Spring '20, are the mechanism for managing permission sets at scale. A PSG bundles multiple permission sets into a single assignable unit. A user gets one PSG assignment rather than six individual permission set assignments. When the bundle needs to change, you update the group — not every user's individual assignments.

PSGs are genuinely useful in complex orgs. The pattern we recommend: one PSG per functional role, composed of individual permission sets that each represent a coherent capability. "Can manage Cases" is a good permission set. "Can access the EMEA Sales Console" is a good permission set. Assigning both to a user via a PSG is clean. Baking both directly into a profile alongside 40 other permissions is not.

Recommended Structure for a 500-User Org

Below is the profile architecture pattern we'd recommend for a mid-to-large org. It won't fit every situation, but it represents the principle: minimise profiles, maximise permission sets.

/*
 * RECOMMENDED PROFILE ARCHITECTURE — 500-USER ORG
 *
 * TIER 1: Baseline Profiles (3-5 max)
 * ─────────────────────────────────────────────
 * Standard User          → base access for all non-admin users
 * Read-Only User         → external stakeholders, partner users
 * System Admin           → internal admins only
 * Integration User       → API-only, no UI login, no licence waste
 * (optional) Community User → if you have Experience Cloud
 *
 * TIER 2: Permission Set Groups (one per functional role)
 * ─────────────────────────────────────────────────────
 * PSG: Sales Rep         → PS: Opportunities + PS: Quotes + PS: Forecasting
 * PSG: Sales Manager     → PS: Sales Rep + PS: Pipeline Reporting + PS: Team Override
 * PSG: Service Agent     → PS: Cases + PS: Knowledge + PS: Live Agent
 * PSG: Service Manager   → PS: Service Agent + PS: Queues Admin + PS: Omnichannel
 * PSG: Finance Viewer    → PS: Contract Value FLS + PS: Revenue Fields
 *
 * TIER 3: Muting Permission Sets (exception handling)
 * ─────────────────────────────────────────────────
 * Muting PS: No Chatter  → for users in regulated roles
 * Muting PS: No Reports  → for users in data-restricted contexts
 *
 * RESULT: 5 profiles. 12 permission sets. Clean, auditable, maintainable.
 * ANTI-PATTERN: 1 profile per user type × 15 types = 15 profiles, each
 *               with 200+ settings to independently audit and maintain.
 */
💡
The Profile Minimisation Migration

If you're inheriting an org with profile sprawl, the migration path is: first, map all profiles to a matrix of permissions and identify which permissions are genuinely unique to each profile. Second, create permission sets for each unique permission cluster. Third, collapse profiles to the minimum baseline set and assign permission sets to users. The last step is the hard one — it requires careful testing. But the alternative is maintaining a permission model that grows more opaque every quarter.

Org-Wide Defaults and the Sharing Model

Org-Wide Defaults (OWD) is the single most consequential security setting in your Salesforce org. It sets the baseline visibility for every record on every object: absent any other sharing configuration, who can see what? Getting this wrong at implementation is expensive to fix later — because changing OWD triggers a sharing recalculation across your entire org, which for large orgs can take hours and cannot be safely done during business hours.

The Three OWD Options and What They Actually Mean

Public Read/Write: Every user in the org can see and edit every record on this object, regardless of ownership. This is the most permissive setting and is appropriate only for reference data or objects where there is genuinely no reason to restrict visibility — custom lookup objects, product catalogues, that kind of thing. For any object containing commercially sensitive or personally identifiable data, Public Read/Write is a governance failure waiting to happen.

Public Read Only: Every user can see every record, but can only edit records they own or that have been explicitly shared with them. This is a reasonable default for objects where visibility should be broad but editing should be controlled — internal knowledge base articles, shared account data in a flat sales organisation.

Private: Users can only see records they own, records that have been shared with them via sharing rules or manual sharing, or records owned by users below them in the role hierarchy. This is the correct starting point for any object containing sensitive data. Work from Private upward — grant access deliberately — rather than starting from Public and trying to restrict it retrospectively.

Why Defaulting to Public Is a Governance Failure

The path of least resistance during implementation is to set most objects to Public Read/Write or Public Read Only. It avoids the configuration overhead of building sharing rules, and it prevents the common implementation-phase complaint that "I can't see the records I need." The problem is that it also makes every user's CRM data visible to every other user — including contract values, pipeline figures, salary data if HR objects are in Salesforce, and customer complaints if cases are in Salesforce.

We have reviewed orgs where inside sales reps could see the full pipeline of enterprise account executives, including deal sizes and close probabilities, because Opportunity OWD was set to Public Read Only and nobody had reviewed the implications. The data was visible in reports, in list views, in global search. Nobody had intended this. Nobody had tested it. It was the default.

Role Hierarchy and Its Interaction with OWD

The role hierarchy determines the reporting structure in Salesforce. A user's manager in the role hierarchy automatically inherits access to all records owned by users beneath them — provided the OWD is Private or Public Read Only. If OWD is Public Read/Write, the role hierarchy has no meaningful impact on data access because everyone can see everything anyway.

Role hierarchy design mistakes are common and hard to undo. The most frequent error is building a role hierarchy that mirrors the organisational chart exactly, which creates hierarchy depth that causes performance issues in large orgs. The correct approach is to design the role hierarchy for data visibility, not for org chart representation. These are related but not identical concerns — a regional manager may need visibility into their team's pipeline without needing to be a separate hierarchy node from the area director.

Sharing Rules: Criteria-Based vs Ownership-Based

Ownership-based sharing rules share records based on who owns them. "Share all Opportunities owned by members of the 'EMEA Sales' group with the 'EMEA Manager' group." They're simple, fast to evaluate, and appropriate when the sharing boundary aligns with ownership.

Criteria-based sharing rules share records based on field values on the record itself. "Share all Opportunities where Region__c = 'EMEA' with the 'EMEA Manager' group." They're more flexible — they decouple sharing from ownership, which is useful when records change ownership during a workflow — but they're also slower to evaluate at scale, because Salesforce must evaluate every record's field values against the rule criteria.

A practical note: there is a hard limit of 300 sharing rules per object. We've seen orgs approach this limit with a sprawling set of criteria-based rules that could have been replaced with a cleaner role hierarchy and three ownership-based rules. When you're building sharing rules, always ask whether the same access requirement could be achieved by redesigning the role hierarchy or OWD before adding another sharing rule.

When Sharing Rules Aren't Enough: Apex Managed Sharing

When the business logic for sharing is too complex for declarative sharing rules — conditional on multiple factors, dynamic based on record state changes, or requiring access grants to individual users rather than groups — Apex Managed Sharing is the right approach. It's programmatic: your Apex code creates AccountShare, OpportunityShare, or custom object share records that explicitly grant access to specific users or groups.

The trade-off is complexity. Apex sharing grants must be managed in code — created when access should be granted, deleted when access should be revoked. If your code doesn't clean up share records correctly, you end up with stale sharing grants that persist after the business reason for them has expired. This is a genuine security risk that declarative sharing rules don't carry.

// APEX MANAGED SHARING EXAMPLE
// Granting a specific user read access to an Account record
// Use case: external account manager needs temporary visibility
// during a handover period — this can't be modelled with standard sharing rules

public class AccountSharingService {

    public static void grantHandoverAccess(Id accountId, Id userId) {
        AccountShare shareRecord = new AccountShare();
        shareRecord.AccountId      = accountId;
        shareRecord.UserOrGroupId  = userId;
        shareRecord.AccountAccessLevel  = 'Read';
        shareRecord.OpportunityAccessLevel = 'None'; // Restrict Opp visibility separately
        shareRecord.CaseAccessLevel = 'None';
        shareRecord.RowCause       = Schema.AccountShare.RowCause.Manual;

        try {
            insert shareRecord;
        } catch (DMLException e) {
            // Duplicate share grants will throw — handle gracefully
            if (!e.getMessage().contains('DUPLICATE_VALUE')) {
                throw e;
            }
        }
    }

    // CRITICAL: Always pair grant methods with revoke methods
    // Stale share records are a persistent security risk
    public static void revokeHandoverAccess(Id accountId, Id userId) {
        List<AccountShare> staleSharesToDelete = [
            SELECT Id FROM AccountShare
            WHERE  AccountId     = :accountId
            AND    UserOrGroupId = :userId
            AND    RowCause      = :Schema.AccountShare.RowCause.Manual
        ];
        if (!staleSharesToDelete.isEmpty()) {
            delete staleSharesToDelete;
        }
    }
}
⚠️
Warning: Apex Sharing Grant Leakage

Every Apex Managed Sharing implementation should have a corresponding revocation strategy. It is not enough to write the grant logic — you must also write, test, and schedule the revocation logic. We have reviewed orgs where Apex sharing grants from three years prior were still active, giving users access to records they had no business reason to see. Treat share record cleanup as a first-class concern, not an afterthought.

Field-Level Security at Scale

Field-level security is the unglamorous workhorse of Salesforce data protection. It's also the area where large orgs most consistently fail. The reason is a combination problem: as your org grows, the number of fields, profiles, and permission sets multiplies, and the FLS configuration space explodes with it.

The Complexity Explosion

Consider a mature enterprise Salesforce org: 150 custom fields on the Account object, 8 profiles, 25 permission sets. The FLS configuration space for just the Account object is 150 × 33 = 4,950 individual Read/Edit/Hidden settings. Multiply that across your full object set and you have tens of thousands of FLS settings to get right and keep current. No individual human can hold this in their head. No standard deployment process ensures it stays correct across releases.

This is why most large orgs have FLS drift — a gradual loosening of field restrictions as projects grant field access to get things working and never revoke it, combined with a creeping expansion of profile permissions as users complain about missing fields and admins take the path of least resistance.

The Pattern That Breaks: Sensitive Fields Visible to the Wrong Roles

The most common FLS failure pattern in enterprise orgs is financial or commercially sensitive fields being visible to frontline users who have no business need for that data. A customer service representative who can see Annual_Contract_Value__c on an Account record is a risk — not because they're untrustworthy, but because that data is outside the scope of their role, and because it expands the blast radius of a credential compromise.

The second-most-common failure is the inverse: a user who should see a field can't, because FLS was set restrictively during development and nobody remembered to open it up for the additional role that was added six months later. This produces support tickets, workarounds, and — in the worst cases — users being added to overly-permissive profiles just to get the field they need.

Sensitivity Tiering: The Practical FLS Architecture

The most maintainable approach to FLS architecture is to tier your fields by data sensitivity and map those tiers to permission sets. Rather than configuring FLS per field per profile, you define a field sensitivity taxonomy and create permission sets that grant access to each tier. Fields belong to a tier; users get tier access through their permission set assignment.

A four-tier model works well in most enterprise contexts:

  • Public: Visible to all authenticated users. Standard CRM fields that have no sensitivity — Account Name, Contact Name, Case Number. Default in your baseline profile.
  • Internal: Visible to all internal employees, not to partners or community users. Most operational CRM data — account owner, case status, opportunity stage. Granted via the baseline internal user permission set.
  • Restricted: Visible only to specific functional roles. Financial data, pipeline values, contract terms. Granted via role-specific permission sets — Finance Viewer, Sales Manager, Legal.
  • Confidential: Visible only to named individuals or the record owner. PII that may not need to be visible to all service agents, compensation data, sensitive case details. Granted via specific individual permission set assignment or Apex-managed FLS overrides.

The tiering model requires discipline at field creation time: every new field must be assigned a tier before it's deployed. This is a governance rule, not a technical one. The technical enforcement is: new fields go into the Hidden FLS state by default on all profiles except System Admin. Access is then granted explicitly through the appropriate tier permission set. This inverts the usual dynamic — access is denied by default, granted by exception — which is the correct security posture.

Enforcing FLS in code is equally important. When Apex queries return records, field values are accessible regardless of the running user's FLS settings — unless you explicitly enforce FLS in your query. The WITH SECURITY_ENFORCED keyword on SOQL queries, or the Security.stripInaccessible() method, should be standard practice in any Apex code that handles sensitive fields.

-- SOQL WITH SECURITY_ENFORCED
-- Forces FLS check at query execution time
-- Fields the running user cannot see will throw a QueryException
-- rather than silently returning data the user shouldn't access

SELECT  Id,
        Name,
        Annual_Contract_Value__c,   -- This field will throw if FLS = Hidden
        Region__c
FROM    Account
WHERE   OwnerId = :UserInfo.getUserId()
WITH    SECURITY_ENFORCED

-- Alternative: use stripInaccessible() in Apex for more granular control
-- SObjectAccessDecision decision = Security.stripInaccessible(
--     AccessType.READABLE,
--     [SELECT Id, Name, Annual_Contract_Value__c FROM Account]
-- );
-- List<Account> safeRecords = (List<Account>) decision.getRecords();

Salesforce Shield and Regulated Industries

Salesforce Shield is a set of premium security products: Platform Encryption, Event Monitoring, and Field Audit Trail. It is sold as a compliance answer, and in regulated industries it often is. But it is also sold in contexts where it isn't necessary, and at a non-trivial cost premium. As a CTO or solution architect, your job is to distinguish between the two.

Platform Encryption: What It Actually Encrypts

Shield Platform Encryption encrypts data at rest within Salesforce's infrastructure — meaning that if Salesforce's storage layer were somehow compromised, your data would be unreadable without the encryption keys. This is a real security control, and in industries where data residency and encryption-at-rest are regulatory requirements, it is necessary.

What it does not do is protect data from authorised Salesforce users. A sales rep who has access to an Account record can still read every field on that record, encrypted or not. Encryption protects against infrastructure-level compromise, not against over-permissioned users. If your primary security concern is users seeing data they shouldn't, the answer is FLS and sharing rules — not encryption.

Platform Encryption also has functional restrictions. Encrypted fields cannot be used in formula fields, in most SOQL WHERE clauses, in roll-up summary fields, or in many standard Salesforce features. Every encrypted field is a potential integration or reporting limitation. These restrictions must be mapped against your business requirements before enabling encryption — we've seen programmes where enabling Shield Encryption broke existing reporting and required a significant rebuild.

Shield Event Monitoring: What You Get and What It Costs

Event Monitoring gives you a detailed audit trail of user activity: which records were accessed, which reports were run, which data was exported, which logins succeeded and failed, and from which IP addresses. This data is available via the EventLogFile API as CSV files, one file per event type per day.

The genuine value is forensic: if you suspect a data breach or need to investigate unusual activity, Event Monitoring gives you the raw material to reconstruct what happened. For regulated industries with audit requirements — financial services, healthcare, legal — this is genuinely necessary and worth the cost.

The limitation is that Event Monitoring is raw data, not an alerting or SIEM system. The log files are available the next day, not in real time. Operationalising Event Monitoring — building the pipelines to ingest the data, the dashboards to surface anomalies, the alerting rules to flag suspicious behaviour — requires engineering effort that is often underestimated when Shield is purchased.

Field Audit Trail: The Compliance Use Case

Field Audit Trail extends the standard Salesforce field history tracking (which retains 18 months of history for up to 20 fields per object) to retain up to 10 years of history for up to 60 fields per object. The compliance use case is straightforward: regulated industries that require long-retention audit trails of data changes need Field Audit Trail. Without it, Salesforce's standard field history is inadequate for GDPR Article 30 record-keeping requirements, SOX change audit requirements, or financial services record-retention regulations.

When Shield Is and Isn't Necessary

Shield is genuinely necessary when: you are in a regulated industry (financial services, healthcare, government) with specific encryption-at-rest or audit-retention requirements; when your information security team has a formal requirement for platform-level event logging; or when your legal team has data retention obligations that exceed Salesforce's standard 18-month field history.

Shield is often sold unnecessarily when: the primary security concern is user over-permissioning (the answer is FLS and sharing); when "encryption" is cited as a vague compliance requirement without a specific regulation attached; or when Event Monitoring is proposed as a "nice to have" without a plan to operationalise the data it produces. At roughly 30% of your base Salesforce licence cost, Shield is a significant line item. The business case should be specific and defensible, not based on security anxiety.

The Security Architecture Checklist

Before any Salesforce org goes live, and as part of any architecture review on a running org, the following areas should be explicitly reviewed. This is not a comprehensive security audit — it's the minimum viable checklist for an architect who takes security seriously.

Pre-Go-Live Review

  • OWD review: Has every object's OWD been explicitly set? Is the default Private for all sensitive objects? Can you justify any object that is not Private?
  • Profile count: How many profiles does the org have? Are all of them in use? Are there duplicate profiles that have diverged without intent?
  • Permission set audit: Can you map every permission set to a functional business requirement? Are there orphaned permission sets from previous projects?
  • FLS spot-check: For every object containing PII or commercially sensitive data, run an FLS report and verify that restricted fields are Hidden for the Standard User profile.
  • Role hierarchy review: Does the role hierarchy reflect data visibility requirements — not just organisational reporting lines?
  • Integration user profiles: Do API integration users have the minimum permissions required for their function? Can they access data they don't need to?
  • Guest user profile (if applicable): If you have Experience Cloud, is the Guest User profile locked down? Guest users are unauthenticated — they should have the most restrictive access of any persona in the org.
  • System-level controls: Are MFA enforcement, login hours, and IP restrictions configured for admin accounts?

The Ten Most Common Security Misconfigurations in Enterprise Orgs

  1. Account and Opportunity OWD set to Public Read Only — everyone in the org can see all pipeline data. Almost never intentional.
  2. Integration users with System Administrator profile — integration accounts should have the minimum permissions required. SysAdmin is never minimum.
  3. Apex code without WITH SECURITY_ENFORCED or stripInaccessible() — FLS bypassed silently in custom code.
  4. Guest User profile with Create/Edit permissions — unauthenticated users should never be able to create or modify records.
  5. Stale Apex sharing grants — share records created programmatically and never cleaned up, persisting long after the business reason expired.
  6. Profiles with "View All Data" or "Modify All Data" — the nuclear option for permissions, used as a shortcut during development and never restricted before go-live.
  7. No MFA on admin accounts — the single most impactful credential security control, often not enforced on legacy admin accounts.
  8. Criteria-based sharing rules evaluating on un-indexed fields — causes sharing recalculation performance issues that manifest as org-wide slowdowns during data changes.
  9. FLS set permissively during UAT and never locked down for production — the "we'll tighten security before go-live" promise that doesn't get kept.
  10. No process for deprovisioning users — departed employees with active licences and credentials, often with high permission levels from their last role.

Red Flags in a Security Architecture Review

When reviewing a Salesforce org's security posture, certain findings should immediately escalate the concern level. More than 20 active profiles suggests profile sprawl and indicates the permission model has grown organically without design. Any profile with View All Data or Modify All Data outside System Admin is almost always a mistake. Any external-facing integration user with more than Read access to financial objects is a risk that should be investigated immediately. A role hierarchy with more than 7 levels of depth suggests an org-chart-driven design that will cause performance problems. And any org that has never had a security review — and has been live for more than two years — should be assumed to have at least three of the misconfigurations listed above.

Key Takeaways

  • Salesforce security operates in four layers — object, field, record, and system — each of which can only restrict, never grant above the layer above it. Diagnose access issues top-down, always starting at the object level.
  • OWD is the most consequential security setting in your org. Start from Private for sensitive objects and grant access upward deliberately. Defaulting to Public during implementation is a governance failure that's expensive to undo.
  • Profiles are the floor, permission sets are extensions. A minimal set of baseline profiles (3–5) combined with permission set groups per functional role is the correct architecture for any org over 200 users.
  • FLS complexity explodes with org size. The practical control is a sensitivity tiering model — four tiers, each represented by a permission set — with new fields defaulting to Hidden and access granted explicitly.
  • Apex code that queries sensitive fields must explicitly enforce FLS via WITH SECURITY_ENFORCED or Security.stripInaccessible(). Without this, FLS is silently bypassed in custom code.
  • Apex Managed Sharing must always pair grant logic with revoke logic. Stale share records are a persistent, invisible security risk that doesn't surface in standard security reviews.
  • Salesforce Shield is genuinely necessary in regulated industries with specific encryption-at-rest or audit-retention requirements. It is often sold as a vague compliance answer — always require a specific regulatory requirement before committing to the cost.

Checkpoint: Test Your Understanding

1. A user has Read access to the Opportunity object on their profile, but a sharing rule grants their public group Read access to all Opportunities owned by users in a different territory. The user also has a permission set that grants Edit access to Opportunities. What level of access does the user have to a specific Opportunity owned by someone outside their role hierarchy and outside the sharing rule criteria?

A. Edit — the permission set grants Edit access to all Opportunities regardless of sharing
B. Read — the profile Read access is the baseline and cannot be reduced by sharing
C. No access — object-level access and field-level security grant what a user can do, but record-level sharing determines which records they can do it on. If the record doesn't meet the sharing criteria, they cannot see it.
D. Read — sharing rules always grant at least Read to all records in a Public Group

2. An enterprise org has 35 profiles, most of which were created by copying an existing profile and making minor modifications. What is the most significant architectural risk this creates?

A. Performance degradation — more profiles cause slower SOQL query execution
B. Permission drift — profiles that diverged from a common ancestor accumulate unknown differences over time, making it impossible to audit or confidently change permissions without risk of unintended access changes
C. Licence cost increase — each additional profile requires an additional Salesforce licence
D. Data model constraints — profile count contributes to the custom object limit

3. A new regulatory requirement mandates that all changes to the Contract_Value__c field must be auditable for seven years. The current org uses standard Salesforce field history tracking. What is the correct response?

A. Enable field history tracking for Contract_Value__c — Salesforce retains field history indefinitely
B. Use a trigger to copy field changes into a custom audit object — this replicates Field Audit Trail functionality without additional cost
C. Enable Shield Platform Encryption for the field — encryption satisfies audit retention requirements
D. Evaluate Shield Field Audit Trail — standard field history retains only 18 months of data. For a seven-year retention requirement, Field Audit Trail (or an external audit log strategy) is required.

Discussion & Feedback