← Back to Platform & Technical
PLAT-001 Platform & Technical 15 min read For: Salesforce Architects

Apex Best Practices for Tech Leaders Who Don't Write Code

You don't need to write Apex to govern it well. Understanding what good Apex looks like — and what warning signs to watch for — lets you hold your development team to the right standards without micromanaging their code.

VS

Vishal Sharma

Salesforce Architecture Specialist · Updated May 2026

What you will learn...
  • What Apex is and where it fits in the Salesforce automation stack
  • The five questions every leader should ask about the Apex in their org
  • What good Apex structure looks like and the anti-patterns that signal risk
  • Code coverage: what the 75% requirement means and why it can be gamed
  • How to read a code review without reading code
  • The governance signals that tell you your Apex practice is healthy or struggling

What Apex Is and Where It Fits

Apex is Salesforce's proprietary programming language — syntactically similar to Java, running server-side on Salesforce infrastructure. It is used for business logic that cannot be expressed in declarative tools: complex calculations, integration callouts, multi-step data processing, and anything requiring programmatic control flow that flows and formulas cannot handle.

In a well-governed Salesforce org, Apex is used selectively — for the logic that genuinely requires it. In a poorly governed org, Apex accumulates: every requirement gets a trigger, helper classes multiply without ownership, and the org develops an Apex debt that eventually slows every deployment and makes every change risky.

As a leader, you do not need to read Apex. But you do need to understand the conditions under which your team's Apex is healthy or degrading — and ask the right questions to find out.

💡
Apex vs Flow distinction: Since 2021, Salesforce's guidance is "Flow first" — use declarative tools before writing Apex. A team that reaches for Apex immediately for every new requirement is either under-skilled in Flow or has a culture that favours code over configuration. Either way, it creates more long-term maintenance cost than necessary.

Five Questions Every Leader Should Ask

You don't need to review code to govern Apex quality. These five questions, asked regularly, surface the problems that matter.

1. "What is our code coverage percentage, and which classes have coverage below 75%?" Coverage below 75% means the code cannot be deployed. Coverage at exactly 75% means tests exist only to satisfy the minimum requirement and likely assert nothing meaningful. Ask for a coverage report — a healthy org has coverage above 90% with tests that assert specific outcomes.

2. "Do we have one trigger per object?" Multiple triggers on the same object create order-of-execution ambiguity — the platform does not guarantee which trigger fires first. Ask your team: how many triggers exist on Account, Opportunity, and Case? If the answer is more than one per object, ask how execution order is managed.

3. "Are there any known SOQL-in-loop issues?" This is the single most common cause of production governor limit exceptions. If your team cannot answer this with confidence, ask them to run a code scan (PMD, Salesforce Code Analyser) and report the results.

4. "When was the last time an Apex class was deleted?" Healthy codebases prune unused code. If no classes have ever been deleted, the org is accumulating debt — old code that is no longer called but cannot be safely removed because nobody is sure what it does.

5. "What happens if a trigger encounters an exception in a batch of 200 records?" The correct answer is: the entire batch fails and rolls back, and error handling logs the exception for investigation. If the answer is "I'm not sure" or "it probably just skips the record", there is a gap in error handling awareness.

🔑
The coverage game: A developer under deadline pressure can write a test that calls every method without asserting anything — just achieving coverage percentage without testing correctness. Ask: "Do our tests verify that the right data was written, or do they just call the methods?" Real test quality is in the assertions, not the coverage number.

Structural Best Practices: What Good Looks Like

Good Apex structure is recognisable even without reading the code in detail. Here are the structural patterns that indicate a well-run Apex practice.

One trigger per object, one handler class per trigger: Every trigger should be thin — it calls a handler class and does nothing else. All logic lives in the handler class. This makes the code testable, readable, and replaceable. A trigger that contains actual business logic (loops, SOQL, DML) is a sign of rushed development.

No hardcoded IDs or values: IDs from one org (a sandbox record ID hardcoded to filter by a specific record type) will not work in another org. Hardcoded IDs are a deployment failure waiting to happen. Configuration values should live in Custom Metadata Types or Custom Labels, not in Apex source code.

Consistent naming: Classes follow a naming convention (OrderService, OrderServiceTest, OrderTrigger, OrderTriggerHandler). Inconsistent naming signals that multiple developers wrote code independently without shared standards — which also means shared quality standards were absent.

Test classes in the same package: Every Apex class should have a corresponding test class. If a developer says "we'll add tests later", the tests will not be added later. Test-with-the-code is the only pattern that works at scale.

💡
Code scanner as a governance gate: Salesforce Code Analyser (PMD-based) can be run automatically as part of a CI/CD pipeline. Configure it to fail the pipeline if SOQL-in-loop, DML-in-loop, or missing test coverage is detected. This moves quality enforcement from "code review opinion" to "automated pipeline gate."

Anti-Patterns That Signal Risk

These patterns in an Apex codebase are indicators of accumulated technical debt that will manifest as production incidents or blocked deployments.

Logic duplicated across multiple triggers: If the same Account update logic exists in three different triggers (one for Order, one for Case, one for Opportunity), any change to that logic requires three synchronised updates — and the risk of inconsistency is constant.

Static variables used to prevent recursion: A common pattern where a static Boolean flag prevents a trigger from firing twice in the same transaction. This pattern is sometimes necessary but often signals that the trigger logic is not idempotent — it cannot be safely called twice. If your team uses this pattern extensively, ask why the triggers are firing recursively in the first place.

Classes with names like "Utils", "Helper", or "Misc": These are catch-all classes that accumulate unrelated methods over time. They cannot be tested as a unit and their methods cannot be safely removed because their callers are unclear. They are a form of technical debt that compounds.

⚠️
The "it works in sandbox" risk: Sandbox data volumes are typically 10-20% of production. Code that works perfectly in sandbox can fail in production when a trigger processes 200 records in a batch instead of 5. Always require volume testing before promoting Apex to production for objects with high record counts.

Governance Signals: Is Your Apex Practice Healthy?

Beyond asking questions, these observable signals tell you whether the Apex practice in your org is healthy or degrading over time.

Healthy signals: Deployments rarely fail due to test coverage. Code reviews happen before every merge. New Apex is written for genuine complexity, not convenience. The team can explain every class's purpose and owner. Technical debt reviews happen quarterly and old code is pruned.

Degrading signals: Deployments frequently fail due to test coverage failures in unrelated classes. Developers add new classes without reviewing existing ones for reuse. The response to "what does this class do?" is "I'm not sure, don't touch it." No Apex has been deleted in two years. Production incidents regularly trace back to governor limit exceptions.

The leading indicator of Apex health is not coverage percentage — it is whether the team can answer questions about their code with confidence. A team that knows their codebase, owns it, and actively maintains it will have healthy Apex metrics as a natural consequence.

Key Takeaways

  • Apex is server-side Salesforce code for logic that declarative tools cannot handle. In a well-governed org it is used selectively; in poorly governed orgs it accumulates as unmaintained debt.
  • Five questions surface most Apex quality problems: code coverage depth, trigger-per-object discipline, SOQL-in-loop issues, codebase pruning frequency, and error handling approach.
  • Good Apex structure: one trigger per object calling a handler class, no hardcoded IDs, consistent naming, and test classes written with the code — not added later.
  • The 75% coverage requirement can be gamed by writing tests that call methods without asserting outcomes. Real test quality is in the assertions — ask whether tests verify results or just achieve coverage percentage.
  • Anti-patterns that signal accumulated risk: logic duplicated across triggers, catch-all utility classes, and static recursion flags masking non-idempotent logic.
  • The leading governance indicator is whether the team can answer questions about their code with confidence — healthy metrics follow naturally from an owned, maintained codebase.

Test Your Understanding

1. A developer reports that their Apex classes have 76% code coverage. A senior developer says this is acceptable because it exceeds the 75% minimum. What follow-up question should a leader ask?

A. No follow-up is needed — 76% exceeds the platform minimum and the code can be deployed
B. Do the tests assert specific outcomes, or do they just call methods to hit the coverage number? Coverage at 76% with no assertions offers no quality protection.
C. Ask whether the coverage was measured in a full sandbox or a developer org, since results vary

2. Your org has three separate triggers on the Account object — one created in 2021, one in 2023, and one in 2025. What is the primary architectural risk this creates?

A. Each trigger consumes separate CPU time, tripling the CPU limit usage for Account operations
B. The platform does not guarantee execution order between multiple triggers on the same object, creating unpredictable behaviour when the triggers interact or depend on each other's results
C. Salesforce automatically merges multiple triggers on the same object, which can cause logic conflicts during the merge

3. A developer argues that testing in sandbox is sufficient before production deployment. Why is sandbox testing alone insufficient for Apex quality assurance?

A. Sandbox environments run a different version of Apex than production, so sandbox results don't apply
B. Sandbox data volumes are typically much lower than production. Code that works with 5 records in sandbox can hit governor limits (SOQL, CPU, heap) when processing 200 records in production bulk operations.
C. Sandbox testing is sufficient — the platform executes the same Apex under the same limits in both environments

Discussion & Feedback