The shortest path is the property syntax with a private backing field and an explicit lazy-load check. The pattern handles 90 percent of controller getter needs.
- Declare the backing field as private
private Account cachedAccount; The field holds the loaded value across multiple getter calls inside the same controller instance.
- Add the property with a custom get block
public Account currentAccount { get { if (cachedAccount == null) cachedAccount = [SELECT Id, Name FROM Account WHERE Id = :recordId LIMIT 1]; return cachedAccount; } private set; }
- Reference the property from Visualforce
{!currentAccount.Name} on the page now reads through the property; the SOQL runs once even if the expression appears five times.
- Invalidate when state changes
When the controller takes an action that changes the underlying record, set cachedAccount = null inside the action method so the next getter call refreshes the data.
- Write the unit test
Create an Account in the test, instantiate the controller with the record ID, call currentAccount, and System.assertEquals on the returned name.
Must be public to be reachable from Visualforce or Lightning bindings.
Any Apex type; primitive, sObject, or custom class.
Java-style getX or C#-style property name. Visualforce maps both to the same expression syntax.
Required to call the getter from JavaScript; add cacheable=true for read-only methods.
- Getters with SOQL run on every Visualforce rerender. A page with five expressions referencing five different SOQL-heavy getters can fire 25 queries per render without caching.
- Side effects inside getters are an anti-pattern. Modifying state, performing DML, or making callouts from a getter breaks the implicit contract that getters are read-only.
- Lazy-load caching survives only inside the controller instance. Visualforce controllers are recreated on each request; the cache does not persist across requests unless persisted to ViewState.
- @AuraEnabled cacheable=true methods cannot perform DML. Mark a method cacheable only when it is genuinely read-only.