Balancing Low-Code Solutions with APEX Best Practices

The Low-Code Revolution

The Salesforce ecosystem has undergone a remarkable transformation in recent years. With powerful configuration tools like Salesforce Lightning Flow and Salesforce Omni Studio reaching new levels of sophistication in 2025, the need for custom APEX code has diminished significantly across many implementation scenarios.

Gone are the days when every Salesforce project demanded a team of experienced developers writing extensive APEX code. Today’s Salesforce platform has embraced the low-code/no-code philosophy, empowering administrators and business analysts to build complex solutions without writing a single line of code in many cases.

The Continued Relevance of APEX

Despite this shift, APEX remains crucial for enterprise-grade implementations with complex business requirements. The reality is that sophisticated Salesforce projects still require custom code to handle intricate business logic, large data volumes, and performance-critical operations.

However, a concerning trend has emerged: as the platform emphasizes low-code solutions, we’re facing a shortage of developers with strong APEX fundamentals. Many new Salesforce professionals have focused primarily on declarative skills, creating a skills gap for projects that require deep programmatic expertise.

Maintaining Standards in a Changing Landscape

When APEX development is necessary, adherence to best practices becomes even more critical. The reduced frequency of coding makes it easier to overlook fundamentals like proper exception handling, bulkification, and test coverage.

As architects and technical leaders, we must provide clear guidance to ensure that when developers do write APEX, they follow established standards that promote maintainability, scalability, and security.

Key Recommendations for APEX Excellence

Below, I’ve compiled essential recommendations that every Salesforce architect should share with their development team at the start of a project. These guidelines ensure that even in our increasingly low-code world, the APEX code we do write meets the highest standards of quality and performance.

1. Bulkify Your Code

Recommendation: Always design APEX code to handle multiple records (bulk processing) using collections like Lists, Sets, or Maps, rather than processing records individually. For example, avoid SOQL queries or DML operations inside loops.


Impact if Ignored: Non-bulkified code can hit governor limits (e.g., 100 SOQL queries or 150 DML statements per transaction), causing runtime failures in bulk operations like Data Loader imports or triggers processing multiple records.

2. Avoid SOQL Queries Inside Loops

Recommendation: Place SOQL queries outside of loops and use collections to store results for processing. For example, query all relevant records once and filter in-memory using a Map.


Impact if Ignored: Each SOQL query in a loop counts toward the 100-query limit, quickly exhausting it in bulk scenarios, leading to “Too many SOQL queries” exceptions and failed transactions.

3. Use Governor Limit-Aware DML Operations

Recommendation: Minimize DML statements by grouping operations (e.g., update a List of records in one update call instead of multiple individual calls). Check Limits.getDMLStatements() if needed.


Impact if Ignored: Excessive DML statements (limit: 150 per transaction) cause “Too many DML statements” errors, breaking functionality during bulk updates or inserts.

4. Implement Proper Exception Handling

Recommendation: Use try-catch blocks to handle exceptions gracefully, logging errors (e.g., to a custom object) and providing meaningful user feedback. Avoid swallowing exceptions silently.


Impact if Ignored: Unhandled exceptions crash the transaction, leave data in an inconsistent state, and frustrate users with cryptic error messages or no feedback at all.

5. Leverage Trigger Frameworks

Recommendation: Use a trigger framework (e.g., a single trigger per object with a handler class) to centralize logic, enforce execution order, and avoid recursion. Include a recursion guard (e.g., static Boolean flag).


Impact if Ignored: Multiple triggers or unorganized logic lead to unpredictable execution order, infinite loops (hitting CPU time limits), and maintenance nightmares.

6. Implement Asynchronous Processing for Long-Running Operations

Recommendation: Use @future methods, Batch Apex, Queueable Apex, or Scheduled Apex for long-running operations and processes that could exceed synchronous execution limits.

Impact if not followed: Long-running operations will time out, hit CPU limits, or create poor user experiences with extended wait times. Critical business processes may fail unpredictably.

7. Implement Security Best Practices

Recommendation: Use with sharing keyword for classes that don’t need to bypass security. Implement proper CRUD, FLS checks before DML operations. Use the Security.stripInaccessible() method to enforce FLS automatically.

Impact if not followed: Security vulnerabilities may allow users to access or modify data they shouldn’t have permissions for, potentially leading to data breaches or compliance violations.

8. Optimize SOQL Queries with Selective Filters

Recommendation: Use indexed fields (e.g., Id, Name, or custom indexed fields) in WHERE clauses and avoid non-selective queries on large datasets. Leverage WITH SECURITY_ENFORCED for security.


Impact if Ignored: Non-selective queries on large objects fail with “Non-selective query” errors in triggers, and unoptimized queries degrade performance, hitting CPU time limits.

9. Use Constants and Custom Metadata for Configuration

Recommendation: Store hardcoded values (e.g., record type IDs, picklist values) in constants or Custom Metadata Types, not directly in APEX code.


Impact if Ignored: Hardcoded values make code brittle, requiring redeployment for simple changes, and increase the risk of errors if values change (e.g., sandbox vs. production mismatches).

10. Write Test Classes with High Coverage and Assertions

Recommendation: Aim for 100% code coverage (minimum 75%) in test classes, testing both positive and negative scenarios, and use System.assert to validate outcomes. Avoid SeeAllData=true.


Impact if Ignored: Low coverage prevents deployment, weak tests miss bugs, and SeeAllData=true creates environment-specific dependencies, leading to production failures.

11. Minimize Use of Global Variables and Methods

Recommendation: Avoid overusing global access modifiers in classes and methods unless required for managed packages or external integrations. Prefer public or private.


Impact if Ignored: Excessive global usage locks code into a rigid structure, complicates refactoring, and exposes unnecessary functionality, increasing security and maintenance risks.

12. Follow Naming Conventions and Code Comments

Recommendation: Use consistent naming (e.g., camelCase for variables, PascalCase for classes) and add concise comments explaining complex logic or business rules.


Impact if Ignored: Poor naming and lack of comments make code hard to read and maintain, slowing down debugging and onboarding for other developers, leading to errors over time.

13. Implement Proper Code Documentation

Recommendation: Document your code with ApexDocs comments. Explain the purpose of classes, methods, complex logic, and non-obvious design decisions. Document method parameters and return values.

Impact if not followed: Poor documentation leads to maintenance problems, longer onboarding time for new developers, and potential errors when modifying code. This becomes more significant as the codebase grows and original authors depart.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top