Setup
Enterprise Territory Management, Unlimited Edition. ~59K Accounts across 16 regions. Account OWD is open and must stay open — reps need to find and identify any account.
This applies to our Sales User profile only (~150 users). Support, Customer Success, SE, Deal Desk, Finance and leadership keep full visibility through an exemption.
The requirement
Accounts stay visible to everyone, but a set of sensitive revenue fields — Acc ACV, ARR, TBookings, Soft ACV, Dec ACV Rollup, VEc counts — must be visible only to sales users in that account's own region. That includes list views, reports, search and the API, not just the record page.
All of them are Currency or Number. Some are stored, some are formulas, two are roll-up summaries from Opportunity.
The problem
Field-level security is resolved per user, not per record. A field is visible to a user on every Account or none. Nothing in the sharing model makes a field's visibility depend on the record being viewed — and I can't restrict the record itself, because the account has to stay globally visible.
What I'm currently considering
Hide the real fields with FLS from the Sales User profile, then expose one formula field per metric that only returns a value when the user's region matches:
Account_ARR_Regional__c (Currency) = IF( $User.Region__c = Region__c, Account_Arr__c, NULL )
User.Region__c would be read-only for sales users and populated from our territory roster. This needs ~15 fields and keeps everything native, but it leans on $User inside a formula, which makes the field non-deterministic and non-indexable — and I'm not sure how that holds up at 59K records.
I've also looked at a child object with its own private sharing, and at per-region or per-geo shadow columns. Each trades away something different — list views, reports, search, or field count.
My question
How would you approach this? I'd genuinely rather hear what people have actually built than have my own idea validated.
Specifically, if you've solved per-record field confidentiality in a real org — what did you land on, and what did it cost you a year later in maintenance?
And if the $User formula approach is a bad idea for reasons I haven't hit yet, I'd like to know before I build 15 of them.
#Answers #Salesforce Developer #Metadata #Territory Modeling #Sales Cloud
Hi Rohan,
Your read on field-level security is right. It's per user, not per record. If a sales user can see ARR, they can see it on every account they're allowed to open, including list views, reports, and the API. Sharing can't hide a field on a record the user can already see.
The formula doesn't get around that. Salesforce enforces field-level security through the formula. If the user can't see Account Arr, a formula that references it comes back blank on every account, including the ones in their region. $User also makes the formula non-deterministic, so you can't index it. At 59k accounts the row count isn't the thing that breaks this. The security check does.
A column per region has the same limit. A permission set is per user, so someone with the North America set sees those columns on every account, not only North America accounts.
What holds up for list views, reports, search, and the API is a child object with private organization-wide defaults, shared to the account's territory or to a group per region. The account stays public. People outside the region don't get the child rows. Dynamic Forms and a screen flow only cover the record page, and your requirement already says that isn't enough.