Your Customer Community Plus portal runs on Person Accounts, the migration batch is creating external users, and somewhere around 50,000 the creation calls start failing. The failure shows up during user provisioning, but the count that tripped is the number of portal accounts held by one internal owner. Whichever fix you choose sets your licence model and years of sharing maintenance, so settle it before go-live.
Which 50,000 limit you are hitting
Two documented limits share the same number, and a third figure keeps turning up in community answers.
The per-owner limit comes from the Salesforce Help article on Experience Cloud site user account ownership. An internal user who owns accounts that have users on role-based licences can own up to 50,000 of those accounts. A role-based licence is one that lets the user be assigned a role, which is what Customer Community Plus gives you. Person accounts count toward it. For business accounts, only those with Account Role Optimization (ARO) enabled count.
The org-wide limit is a separate thing. By default an org can use 50,000 roles across all of its customer portals, partner portals and communities combined. Salesforce sends an alert at 95% of the limit, and once it is reached you can't create more users. ARO helps because it delays creating an account role until a second user exists on the account. Help doesn't give a raised ceiling for the role limit. If you expect to need more, it points you to your account representative.
The third figure is 1,000 person-account portal users per owner, which you will find in community posts. The current Help text doesn't mention it and gives 50,000, so plan against 50,000. Users on the non-role-based Customer Community licence don't count toward the per-owner limit at all, which matters for the licence decision below.
A published case on SalesforceCodex shows how this plays out. An e-commerce company was moving about 200,000 existing customers into a self-service portal built on Person Accounts and the Customer Community Plus Login licence. Partway through creating external users, the internal owner of the accounts reached 50,000. The team asked Support for an increase and was refused.
Run these two queries before any load, from the Salesforce CLI or the Developer Console query editor. Keep them out of Apex: every row behind the aggregate counts against the 50,000 query-row governor, so on a large org the query fails at exactly the moment you need its answer.
SELECT OwnerId, Owner.Name, COUNT(Id) portalAccounts
FROM Account
WHERE IsPersonAccount = true
AND IsCustomerPortal = true
GROUP BY OwnerId, Owner.Name
HAVING COUNT(Id) > 35000
ORDER BY COUNT(Id) DESC
The 35,000 threshold leaves you some warning room. Then check how your active external users split between licence types:
SELECT UserType, COUNT(Id) activeUsers
FROM User
WHERE IsActive = true
AND UserType IN ('PowerCustomerSuccess', 'CspLitePortal')
GROUP BY UserType
PowerCustomerSuccess is Customer Community Plus and CspLitePortal is the high-volume Customer Community licence. If the PowerCustomerSuccess count is heading towards 50,000, look at both limits now, before the next load does it for you.
Decide the licence before the ownership model
The obvious move is an ownership workaround, but I would start one step earlier and ask whether the portal needs role-based sharing at all.
In a B2C self-service portal, customers log in to see their own orders, cases and preferences. That matches the case study, and the non-role-based Customer Community licence handles it. Without a role per account the ownership cap no longer applies. Help's scale guidance also puts Customer Community at 100+ million users, against 1+ million for Customer Community Plus (10+ million with ARO). For that scenario I would pick Customer Community and stop there.
Plus earns its cost when visibility has to flow through the role hierarchy, for example users on a parent account who need child account records and reports over what is shared to them. Those are the capabilities you give up on the high-volume licence. List every portal requirement and check each one against Customer Community before you commit. Changing licence after go-live means reprovisioning users and rebuilding sharing, which costs far more than doing that check now.
Staying on Plus: the person account owner power user
If you do need Plus, the cleanest way past the per-owner cap is PersonAccountOwnerPowerUser. It represents a user who can own more than 50,000 customer or partner portal accounts, and it is available in API version 57.0 and later. Its object fields include UserId, PortalType, DeveloperName, MasterLabel and Language.
You create the record through the API, and anonymous Apex from the Developer Console or the CLI is the simplest route. This example looks up a dedicated owner by username and registers it for customer portal accounts:
// Anonymous Apex. Deferred sharing must be off before you run this.
User b2cOwner = [
SELECT Id, UserRole.DeveloperName
FROM User
WHERE Username = '[email protected]'
AND IsActive = true
LIMIT 1
];
PersonAccountOwnerPowerUser ownerRegistration = new PersonAccountOwnerPowerUser(
UserId = b2cOwner.Id,
PortalType = 'Customer'
);
insert ownerRegistration;
System.debug('Registered ' + b2cOwner.Id + ' in role ' + b2cOwner.UserRole.DeveloperName);
Help names the portal type values Customer and Partner. The field reference lists PortalType as a picklist without its values, so describe the field in a sandbox to confirm the exact value before you run the insert in production:
for (Schema.PicklistEntry entry :
Schema.PersonAccountOwnerPowerUser.PortalType.getDescribe().getPicklistValues()) {
System.debug(entry.getValue() + ' (' + entry.getLabel() + ')');
}
Keep the script in your repository so the step is repeatable, and run it as a post-deployment task in each org.
Two constraints come with it, and they are permanent:
- The user must sit at the root of the role hierarchy. Its role can't be changed, can't look up to a parent role and can't be reparented.
- You can't create the record while deferred sharing is on. Turn deferred sharing off, create the record, then turn it back on. Book that window in advance, because a sharing recalculation follows it.
Because the power user's role can't be changed or reparented, a later hierarchy clean-up can't move it and set off a sharing recalculation across every portal account it owns. That also means the owner should be a dedicated, non-human user that nobody will ever need to reorganise. Name it so its purpose is obvious and record why it sits at the top.
Spreading ownership across several owners
The other route on Plus is to keep every owner below 50,000. For 200,000 customers, SalesforceCodex suggests five owners holding 40,000 each. It needs no special setup. Assign the owner at provisioning time so the result is deterministic:
public with sharing class PortalOwnerAllocator {
// Ordered list of internal owner user Ids, loaded once per transaction
private static List<Id> owners;
public static Id ownerFor(String customerNumber) {
if (owners == null) {
owners = new List<Id>();
for (User u : [
SELECT Id FROM User
WHERE IsActive = true
AND UserRole.DeveloperName = 'B2C_Portal_Owner_Pool'
ORDER BY Username
]) {
owners.add(u.Id);
}
}
if (owners.isEmpty()) {
throw new IllegalStateException('No portal owners configured');
}
Integer bucket = Math.mod(Math.mod(customerNumber.hashCode(), owners.size()) + owners.size(), owners.size());
return owners[bucket];
}
public class IllegalStateException extends Exception {}
}
Hashing the customer number means a re-run of the same load gives each account the same owner, so retries leave ownership where it was. Adding a sixth owner changes the modulus and remaps the buckets, so look up the existing owner first and only call ownerFor for accounts that don't have one yet. Hash buckets are also uneven, so one owner can creep past 50,000 as the customer base grows. Schedule the owner-count query above and it will catch that.
Most of the cost comes after launch. Every owner shows up in sharing rules, report filters, assignment logic and any automation that checks ownership. Each one is a user you have to license and keep active in the right role for as long as the portal runs. Distributing ownership also does nothing for the org-wide role count, because Plus accounts with portal users still need their roles whoever owns them.
Choosing, and what to check before go-live
Help lists a Support increase to the per-owner limit as an option, and you can request one. Just keep it out of the plan. The case study team asked and was refused, and finding that out mid-migration leaves you redesigning against a deadline.
| Option | Per-owner cap | Org-wide role limit | Capability lost | Long-term cost | When I would use it |
|---|---|---|---|---|---|
| Customer Community licence | Does not apply | Not consumed | Role-based sharing and the Plus features built on it | Low | B2C self-service where users see only their own records |
| PersonAccountOwnerPowerUser | Removed for that owner | Effect not yet confirmed (sources disagree) | None on the licence | One frozen root-level role, a deferred-sharing window at setup | Plus is required and one dedicated owner is acceptable |
| Distribute across owners | Avoided while each owner stays under 50,000 | Still consumed | None | Every owner maintained in sharing, reports and automation | Plus is required and you need a bridge until the power user window is booked |
| Support increase | Possibly raised | Separate request via your account representative | None | Uncertain approval with no fallback | Never as the primary plan |
Before go-live:
- Write down every portal visibility requirement and mark the ones that need role-based sharing.
- Choose the licence from that list, and get sign-off on what Customer Community gives up if you pick it.
- If you stay on Plus, create the power user in a sandbox first and confirm the PortalType value.
- Estimate the total role count across every portal and community against the org-wide 50,000, and enable ARO for business accounts where it fits.
- Schedule both SOQL monitors to run regularly, and have someone own the results.
- Run the user-creation path at full production volume in a full sandbox.
What to watch for
- Distributing ownership leaves the org-wide role limit untouched. For the power user, the sources disagree: Help lists power users as a way to increase the number of roles, while SalesforceCodex says the power user doesn't raise the org-wide role allocation. That is not yet confirmed, so measure role consumption in a full sandbox and treat the 95% alert as a hard stop for planning.
- The 1,000 per-owner figure in community answers isn't in the current Help text. Plan on the 50,000 that Help states, and recheck the article before each major release.
- Creating a PersonAccountOwnerPowerUser needs deferred sharing switched off. Do it outside peak hours and expect a recalculation afterwards.
- If you run a mix of licences, the UserType query shows how many users still sit on PowerCustomerSuccess and count against both limits.
- If you buy login-based licences, Help gives a 1-to-20 ratio of monthly logins purchased to login licences provisioned. Size the purchase from that ratio.
- Allocation by hash spreads accounts roughly evenly at best. Monitor the busiest owner, since the average tells you nothing about who will hit the cap first.
Leave a Comment