Apex Enterprise Patterns (fflib): A Critical Analysis of Scalability vs. Overhead
An honest look into why the industry’s most famous pattern might be your best friend or your worst nightmare, and how to find the balance in modern Salesforce architecture.
André Rödel
5/7/20263 min read
If you have spent more than a few months working in a large-scale Salesforce environment, you have likely encountered the "Big Trigger" problem. You know the one: a single file with two thousand lines of code, nested loops, and enough if-else statements to make even a seasoned developer dizzy.
As a Salesforce Developer/Architect, you eventually realize that "it works" is not a high enough standard. The real challenge is: Can I change it without breaking everything else? This is where the Apex Enterprise Patterns (fflib) come in. Created by Andrew Fawcett and adopted by thousands of teams, this framework is often treated as the "Gold Standard." But is it always the right choice?
Let’s take a deep, human look at the reality of using fflib in the real world.
1. The Pillars of the Pattern
Before we critique it, we have to understand what it’s actually trying to do. The framework is built on Separation of Concerns (SoC), dividing your code into four specific layers:
The Selector Layer: This is where your SOQL queries live. Instead of having queries scattered across twenty classes, you centralize them. This ensures consistency and makes it easy to add security checks like WITH USER_MODE.
The Domain Layer: This layer handles record-level logic. If an Account name shouldn't be changed after it’s "Active," that rule belongs here. It’s about the behavior of the object itself.
The Service Layer: The "Orchestrator." It doesn't care how the data is queried or what the object rules are; it just knows the business process. It’s the entry point for your LWCs, APIs, and Flows.
The Unit of Work (UoW): This is the unsung hero. It manages your DML operations, ensuring they are batched together at the end of a transaction to respect Governor Limits.
2. The "Love" Side: Why It Wins
The primary reason to use fflib is predictability. When a team follows these patterns, you don't have to hunt for logic. You know exactly where a query lives and where a business rule is enforced.
But the real "Superpower" is Unit Testing.
Standard Salesforce tests are slow because they require DML and SOQL. With fflib and its Apex Mocks integration, you can write "True Unit Tests." You can mock the database entirely. This means your test suite that used to take 30 minutes to run might only take 2. For an architect managing a CI/CD pipeline, that time saving is invaluable.
3. The Critical Analysis: Where the Friction Starts
Now, let’s be honest. If fflib is so great, why doesn't everyone use it?
The "Boilerplate" Problem
The most common complaint is the sheer amount of code required just to do something simple. To query one field from a contact, you need a Selector class, an Interface, and a Service call. For a small project, this feels like overkill. It can feel like you are writing more "framework code" than actual "business code."
The Learning Curve
Teaching a junior developer or someone coming from a declarative background how to navigate Dependency Injection and Service Providers is a tall order. It requires a level of abstraction that can be intimidating. If your team isn't fully "all-in," you end up with a "Hybrid Nightmare" where half the code is fflib and the other half is legacy spaghetti.
Performance and Memory
Every layer of abstraction has a cost. While the overhead is usually negligible for a standard UI interaction, in high-volume processing, the instantiation of multiple classes and the handling of generic SObject lists can put pressure on the Heap Size. As a Salesforce Developer/Architect, you must monitor this closely when dealing with Large Data Volumes (LDV).
4. Finding the Middle Ground
Is fflib a "Yes/No" choice? Not necessarily. Here is how I approach the "Critical Analysis" in practice:
Don't Over-Engineer Small Orgs: If you are in a small environment with three objects and five users, fflib is like using a sledgehammer to crack a nut. Keep it simple.
Adopt the Selector First: Even if you don't use the rest of the framework, centralizing your SOQL into Selectors is an immediate win for any org. It’s the "gateway drug" to better architecture.
Interfaces are Optional (Until They Aren't): You don't always need an Interface for every Service. If you aren't planning to mock that service or provide multiple implementations, save yourself the boilerplate.
5. Final Verdict
The Apex Enterprise Patterns aren't just about code; they are about discipline.
If you are building an ISV package or working in a massive enterprise org with 20+ developers, the "cost" of the boilerplate is a small price to pay for the "benefit" of not having the org collapse under its own weight in two years.
However, always remember the goal: Simple, direct, and clean logic. If the framework is making your logic harder to understand rather than easier, you’ve lost the battle. Use the patterns to serve your architecture; don't let the architecture serve the patterns.
Connect
Reach out for feedback or technical inquiries.
© 2026. All rights reserved.
