In FFLIB, a Domain enforces CRUD security and sharing rules by default. We use FFLIB Domains for implementing triggers. In the Salesforce standard, triggers run in system context, meaning they don't enforce CRUD security, and don't enforce sharing rules if "with sharing" is omitted from the class declaration. In almost every use case, we want to keep the Salesforce standard behaviour. For that, we reflected on the fact that triggers are fix business processes running in the background. They should run through regardless of what permissions the current user has. In addition, the user is often not even aware of these processes, so a trigger run that fails due to missing permissions would lead to an error message quite confusing to the user. So we are considering to patch fflib_SObjectDomain in our org to not enforce the permissions by default.

Our discussion lead us to the question: why does the FFLIB framework enforce CRUD security and sharing rules by default for Domains?

Your answer is highly appreciated and helps us, and the community, to better understand the security implications of the framework.

Best regards,

Daniel Wutz

  • Grappled with similar problems here and in other technologies. Nowadays I just follow security rules for everything real-time - regardless of where that logic is. Anything that needs more permissions will be async to the transaction - e.g. user action has to update a total field on a grand parent record. Check whether user has access for a transaction in triggers to avoid raising errors to users. In general, this method of doing things is easier to maintain (IMO). Dec 11, 2020 at 12:42
  • 1
    @PrashanthK Fair enough to check for permissions. But then you'd have to do it every time, in each and every trigger case, which causes overhead in both developing and reading the triggers. Because most of our triggers update fields, quite often ones the users don't have access to. And how would a forked async transaction help? The async transaction runs in the same context it was invoked from, i.e. user context, and not system context. Dec 11, 2020 at 12:57

1 Answer 1


I believe the answer is the fflib was originally designed for the ISV world where such checks are desired. By having all your domain classes inherit from an intermediary class, say ApplicationDomain that extends fflib_SObjectDomain, you can switch off the CRUD checking in one spot.

This is covered in Salesforce Lightning Platform Enterprise Architecture 3rd Edition page 210:

public inherited sharing abstract class ApplicationDomain extends fflib_SObjectDomain {
  public ApplicationDomain(SObject[] records) {

and each domain class (here, Contestants) looks like:

public inherited sharing class Contestants extends ApplicationDomain {
  public Contestants(Contestant__c[] contestants) {

If you are using fflib and do not have this book, stop what you are doing and buy it as it is full of tips for getting the most out of fflib.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .