CRM & SaaSvAPI v63.0Updated 2026-07

Apex

Apex is Salesforce's proprietary, strongly-typed, Java-like programming language that runs on Salesforce servers. It enforces governor limits and provides native access to SOQL, DML, and the Salesforce object model.

Overview

  • 1Apex is the primary backend language on the Salesforce Platform — used for triggers, services, and REST APIs.
  • 2Apex runs in a multi-tenant environment governed by CPU, DML, SOQL, and heap limits per transaction.
  • 3Strongly typed, object-oriented — syntax resembles Java; no memory management required.
  • 4Asynchronous patterns (Batch, Queueable, Scheduled, @future) bypass synchronous governor limits.
  • 5Apex Test classes with System.assert() methods are mandatory — 75% code coverage required to deploy.

Key Features

SOQL inline: `List<Account> accs = [SELECT Id FROM Account WHERE Industry = :industry]`
DML: insert, update, upsert, delete, undelete, merge on SObject records
Triggers: before/after insert/update/delete/undelete on any SObject
Governor Limits enforcement: CPU (10s sync), SOQL (100 queries), DML (150 statements)
Apex Test framework: @isTest, Test.startTest()/stopTest(), Test.setMock()
REST API: @RestResource(urlMapping='/myendpoint/*') + @HttpGet, @HttpPost methods
Batch Apex: Database.Batchable<SObject> processes up to 50 million records asynchronously

Language Fundamentals

  • Data types: Integer, Long, Decimal, Double, String, Boolean, Date, DateTime, Id, Blob
  • Collections: List<T>, Set<T>, Map<K,V> — must be typed; no raw collections
  • SObjects: strongly-typed database records — Account a = new Account(Name='ACME')
  • Null safety: Apex does not throw NullPointerException for SObject field access on null (returns null)
  • String methods: split(), contains(), format(), escapeSingleQuotes(), valueOf()
  • Exception handling: try/catch/finally; DmlException, QueryException, LimitException

SOQL & SOSL

  • SOQL: `[SELECT Id, Name, Account.Name FROM Contact WHERE CreatedDate = THIS_YEAR]`
  • Relationship queries: parent traversal (`Account.Name`) and child subqueries (`(SELECT Id FROM Contacts)`)
  • Aggregate functions: COUNT(), SUM(), AVG(), MIN(), MAX() with GROUP BY
  • Dynamic SOQL: `Database.query('SELECT Id FROM ' + objectName + ' WHERE Name = :name')`
  • SOSL: full-text search across multiple objects — `[FIND 'Acme*' IN ALL FIELDS RETURNING Account, Contact]`
  • Binding variables: always use `:variableName` in SOQL to prevent SOQL injection

Asynchronous Patterns

  • @future(callout=true): run a method asynchronously in a new transaction; no SObject params
  • Queueable: implements Queueable; can chain jobs, pass complex data types
  • Batch Apex: start()/execute()/finish() process millions of records in chunks of 200
  • Schedulable: `System.schedule('Job', '0 0 12 * * ?', new MyJob())` — cron-like scheduling
  • Platform Events: publish/subscribe event-driven messaging within and outside Salesforce
  • Outbound Messaging: push notifications to external endpoints on record save

Testing & Deployment

  • @isTest annotation marks test classes — they do not count toward code coverage limits
  • Test.startTest() / Test.stopTest() creates a new set of governor limits for the code under test
  • Test.setMock(HttpCalloutMock.class, new MyMock()): mock HTTP callouts in tests
  • TestDataFactory pattern: centralise record creation with static factory methods
  • 75% Apex code coverage required to deploy to production (aim for 90%+)
  • Salesforce CLI: `sf apex test run --test-level RunLocalTests --synchronous`

Frequently Asked Questions

What are Salesforce governor limits and why do they exist?

Governor limits cap resource consumption per Apex transaction in Salesforce's multi-tenant environment — ensuring no single customer monopolises shared infrastructure. Key limits: 100 SOQL queries, 150 DML statements, 10 seconds CPU time, 6MB heap per transaction. Design patterns like bulkification (process records in List/Map, not row-by-row) and asynchronous Apex are the standard responses to governor limits.

What is the difference between trigger and Flow for automation?

Apex Triggers run before or after DML operations and execute code with full programmatic control. Record-Triggered Flows (Salesforce preferred) are declarative and managed in Flow Builder without code. Salesforce recommends Flow-first: use Flow when the logic is achievable declaratively; use Apex Trigger (calling a Trigger Handler class) only for complex logic, external callouts, or performance-critical scenarios.

How do I avoid SOQL injection in Apex?

Always use binding variables (`:variableName`) in SOQL queries instead of string concatenation. Binding variables are treated as data, not code, and cannot inject SOQL syntax. For dynamic SOQL, use `String.escapeSingleQuotes(input)` on any user-supplied strings before concatenation. The static SOQL approach with bindings is always preferred.