How to Create a Portal User Using a Record-Triggered Flow in Salesforce
Automating portal user creation is one of the more powerful things you can do inside Salesforce — and record-triggered flows make it possible without writing a single line of Apex code. But getting it right depends on understanding exactly what's happening under the hood, where the permissions live, and what variables in your own org will shape the outcome.
What Is a Record-Triggered Flow?
A record-triggered flow is a type of Salesforce automation that fires automatically when a record is created, updated, or deleted. Unlike screen flows (which require user interaction), record-triggered flows run in the background — making them ideal for tasks like provisioning access, sending notifications, or, in this case, creating a community or Experience Cloud portal user.
When a Contact record meets certain criteria — say, a field is set to "Active" or a checkbox is checked — the flow can immediately spin up a portal user account tied to that Contact.
Why Use a Flow Instead of Apex?
Traditionally, creating portal users required Apex triggers because the Site.createExternalUser() method was the standard approach. Flows have matured significantly, and Salesforce now supports user creation through the Create Records element inside flows, provided your org meets specific prerequisites.
Key advantages of the flow approach:
- No deployment needed — flows are built and activated entirely in the Setup UI
- Easier maintenance — admins without coding skills can modify logic
- Built-in error handling — flows support fault paths visually
- Governor limit awareness — flow actions are somewhat more forgiving for admins managing complexity
The tradeoff is that flows have their own limitations around mixed DML operations, which is one of the most important variables to understand before you build.
The Mixed DML Problem — and How to Handle It ⚠️
This is where many admins get tripped up. Salesforce separates setup objects (like User) from non-setup objects (like Contact, Account). Performing DML on both in the same transaction throws a Mixed DML Exception.
Because a record-triggered flow fires in the context of the record that triggered it (a non-setup object like Contact), you cannot directly insert a User record in the same transaction.
The standard solution is to use a subflow or an invocable action that runs the User creation in a separate transaction. Common approaches include:
| Approach | How It Avoids Mixed DML | Skill Level Required |
|---|---|---|
| Invocable Apex method | Runs User creation outside the trigger context | Intermediate (requires Apex) |
| Asynchronous subflow via Platform Event | Fires a Platform Event; a separate flow processes User creation | Advanced |
| Screen Flow launched from record page | User-initiated; separate context by design | Beginner–Intermediate |
Flow + @future Apex action | Apex runs asynchronously after trigger | Intermediate |
For a fully declarative approach with no code, the Platform Event pattern is the cleanest: the record-triggered flow publishes a Platform Event, and a separate event-triggered flow subscribes to it and creates the User in a fresh transaction.
Step-by-Step: The Core Logic
Regardless of which pattern fits your org, the logical structure of the flow stays consistent.
1. Set Your Entry Conditions
Define precisely when the flow should fire. Common triggers:
- A Contact record is created with a specific record type
- A field like
Portal_Access__c(checkbox) is set totrue - A status field changes from "Pending" to "Approved"
Use the Entry Conditions and Run Flow settings carefully — set it to run only when the record is created or when the relevant field changes, not on every save. This prevents duplicate user creation attempts.
2. Check for an Existing User
Before creating anything, query for an existing User tied to the Contact's Id using a Get Records element. If a User already exists, route the flow to a fault path or simply exit. Skipping this check is a common source of duplicate-user errors.
3. Assign the Correct Profile and Role
Portal users require a profile associated with your Experience Cloud site. The profile must be an external profile — typically Customer Community, Customer Community Plus, or Partner Community, depending on your license type. 🔑
Your flow will need to:
- Reference the correct Profile Id (store this in a Custom Metadata Type or Custom Setting to avoid hardcoding)
- Optionally assign a Role if your community uses role-based visibility
- Set
IsPortalEnabled=trueon the User record
4. Populate Required User Fields
At minimum, a portal User record requires:
FirstName,LastNameEmail(also used asUsername— must be globally unique across all Salesforce orgs)AliasTimeZoneSidKey,LocaleSidKey,EmailEncodingKey,LanguageLocaleKeyProfileIdContactId(links the User to the Contact and automatically setsAccountId)
The Username uniqueness requirement is a significant variable — if your org generates usernames from email addresses, duplicate emails across records will cause failures. Many teams append a domain suffix (e.g., [email protected]) to ensure uniqueness.
5. Handle Errors Gracefully
Always connect a Fault Path from your Create Records element. Log the error to a custom object, send an email alert to an admin, or update a status field on the Contact. Silent failures in background flows are difficult to diagnose without this.
Variables That Will Affect Your Specific Implementation
No two Salesforce orgs have identical configurations. The factors that most directly shape how this flow behaves in your environment:
- Experience Cloud license type — Community, Partner, Customer Plus, and others each have different capabilities and profile options
- Org sharing model — OWD settings and sharing rules interact with portal visibility in ways the flow itself doesn't control
- Username generation strategy — how your org enforces uniqueness determines whether automation can be fully hands-off
- Existing automation conflicts — other flows, process builders, or Apex triggers on the Contact or User object can interfere
- Governor limits in high-volume orgs — bulk Contact imports trigger flows in bulk; testing with real data volumes matters
- API version — some flow features behave differently across Salesforce releases, particularly around asynchronous execution
The right pattern — declarative Platform Events, Invocable Apex, or a hybrid — depends on what your org already has in place, what your team can maintain, and how often portal users will be created. Each of those is something only your setup can answer.