1. Always Bulkify Your Code
Triggers and classes must handle collections, not single records. Replace trigger.new[0] logic with loops over trigger.new. Every operation should work whether one record or 200 records are processed.
2. Never Put SOQL or DML Inside a Loop
This is the most common mistake. A SOQL query inside a for loop can hit the 100-query governor limit instantly. Collect IDs first, query once outside the loop, then process results.
3. Use Maps for Lookups, Not Nested Loops
Instead of looping through a list to find a matching record, build a Map<Id, SObject> from your query result. Map lookups are O(1) and eliminate nested loop performance issues.
4. One Trigger Per Object
Multiple triggers on one object fire in unpredictable order. Use a single trigger that delegates to a handler class. This keeps logic testable, readable, and execution-order predictable.
5. Write Meaningful Test Classes — Aim for 90%+
The 75% minimum is a floor, not a target. Tests should cover positive cases, negative cases, and bulk scenarios (200 records). Use @TestSetup to share test data efficiently.
6. Handle Exceptions Explicitly
Don't swallow exceptions with empty catch blocks. Log them using System.debug in sandboxes or a custom logging object in production. Always use Database.insert(records, false) with SaveResult checks when partial success is acceptable.
7. Avoid Hardcoding IDs
Record Type IDs, Profile IDs, and Queue IDs change between orgs. Query for them by name at runtime, or use Custom Metadata / Custom Settings to store environment-specific values.
8. Use @future and Queueable Thoughtfully
@future methods can't be chained and accept only primitive parameters. Prefer Queueable when you need object parameters, chaining, or better monitoring. Use Batch Apex only for large data volumes exceeding 50,000 records.
9. Keep Triggers Logic-Free
Triggers should contain only context routing — no business logic. All real logic belongs in a handler or service class. This makes unit testing straightforward without needing DML in every test.
10. Use Custom Metadata for Configuration
Business rules that change per environment (thresholds, feature flags, API endpoints) belong in Custom Metadata Types, not hardcoded constants. They're deployable, version-controllable, and query-free in Apex.
Following these practices consistently will keep your code clean, maintainable, and well within Salesforce governor limits — whether you're working in a sandbox or handling millions of production records.