When developing custom Visualforce interfaces in Salesforce, maintaining data continuity during form submissions and partial page refreshes is critical. Because HTTP is inherently stateless, Salesforce uses View State to track non-static Apex controller variables and component hierarchies. Optimizing this state payload is essential to prevent runtime errors and latency.
1. Understanding the View State Lifecycle and Limits
The View State holds everything needed to reconstruct a Visualforce page on subsequent postbacks:
- Apex Controller State: All non-transient, non-static member variables (sObjects, primitives, lists, and maps).
- Component Hierarchy: Structural state of Visualforce tags inside
<apex:form>. - Controller Extensions & Standard Controllers: Internal record data and tracking IDs.
- Maximum Limit: 135 KB per Visualforce request.
- Primary Optimization Tool: The
transientkeyword in Apex. - Diagnostic Utility: View State Inspector tab in Developer Console.
- Impact of Limit Breach: Fatal
Maximum view state size limit (135KB) exceededruntime exception.
2. Implementing View State: Visualforce & Apex
The following example demonstrates how user inputs bind to controller variables and how to use the transient keyword to prevent large read-only query results from bloating the View State.
ViewStateDemo.page)
<apex:page controller="ViewStateController" tabStyle="Account">
<apex:form>
<apex:pageMessages />
<apex:pageBlock title="Account Quick Creator">
<apex:pageBlockSection columns="1">
<apex:inputText value="{!accountName}" label="Account Name" required="true" />
<apex:inputText value="{!accountIndustry}" label="Industry" />
</apex:pageBlockSection>
<apex:pageBlockButtons location="bottom">
<apex:commandButton action="{!saveAccount}" value="Save Account" />
</apex:pageBlockButtons>
</apex:pageBlock>
<apex:pageBlock title="Recent Accounts (Read-Only via Transient)">
<apex:pageBlockTable value="{!recentAccounts}" var="acc">
<apex:column value="{!acc.Name}" />
<apex:column value="{!acc.Industry}" />
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>
ViewStateController.cls)
public with sharing class ViewStateController {
// Preserved in View State across user submissions
public String accountName { get; set; }
public String accountIndustry { get; set; }
// 'transient' prevents large read-only lists from being serialized into View State
public transient List<Account> recentAccounts;
public List<Account> getRecentAccounts() {
if (recentAccounts == null) {
recentAccounts = [
SELECT Id, Name, Industry
FROM Account
WITH USER_MODE
ORDER BY CreatedDate DESC
LIMIT 10
];
}
return recentAccounts;
}
public PageReference saveAccount() {
if (String.isNotBlank(accountName)) {
Account newAcc = new Account(
Name = accountName.trim(),
Industry = accountIndustry
);
insert as user newAcc;
ApexPages.addMessage(new ApexPages.Message(
ApexPages.Severity.CONFIRM,
'Account created successfully!'
));
// Clear input fields
accountName = '';
accountIndustry = '';
}
return null; // Refresh page state
}
}
3. Common Traps & View State Optimization Best Practices
Declaring
public List<Opportunity> oppList { get; set; } and querying 500 records stores all field values, object schemas, and internal relationship data directly inside the page's View State payload. This easily pushes the size past the 135 KB threshold. Mark read-only display lists as transient or use custom lightweight wrapper classes containing only the required string values.
- Use the
transientKeyword: Applytransientto variables, lists, and calculated properties that do not need to persist across postback cycles. - Limit Fields in SOQL Queries: Avoid querying entire sObject records; retrieve only the specific fields rendered on the screen.
- Segment Forms: Only place components that submit data inside
<apex:form>tags. Static outputs outside form tags are excluded from the View State. - Monitor via Development Mode: Enable "Development Mode" and check the View State tab in your footer inspector to analyze byte-size consumption by component and variable.
Summary
Effective View State management is key to building fast, scalable Visualforce pages in Salesforce. By understanding the 135 KB platform limit, using the transient keyword for read-only datasets, and structuring forms cleanly, developers can eliminate runtime exceptions and deliver smooth, responsive user experiences.