Visualforce Page
A Visualforce Page is a Salesforce-side rendered web page built with the Visualforce markup language, an XML-based framework introduced in 2008 to build custom UI on the Salesforce platform.
Definition
A Visualforce Page is a Salesforce-side rendered web page built with the Visualforce markup language, an XML-based framework introduced in 2008 to build custom UI on the Salesforce platform. Each page is a .page file containing tag-based markup that mixes HTML with Visualforce tags (apex:page, apex:form, apex:inputField, apex:commandButton). A backing Apex controller (standard, extension, or custom) provides the data and handles form submissions.
Visualforce was the workhorse UI framework for Salesforce Classic and the first generation of custom apps. It is supported in Lightning Experience but appears inside an iframe wrapper, which limits interactivity and visual integration. Salesforce has been clear that Lightning Web Components are the strategic direction for new custom UI; Visualforce remains for legacy support, very specific use cases (email templates, PDF rendering, certain Sites pages), and the substantial codebases that already exist in production orgs. Most modernization roadmaps include a multi-year Visualforce-to-LWC migration.
How Visualforce Pages fit into modern Salesforce development
Tag-based markup and the controller pattern
A Visualforce Page is a tag-based template that mixes HTML with apex: prefixed Visualforce tags. The tags handle form rendering, input binding, output formatting, and action invocation. Each page has a backing controller: standard controller (auto-generated for one sObject type, provides save/cancel/edit), standard controller with extension (adds custom methods to standard CRUD), or custom controller (entirely custom Apex class). The MVC separation is explicit: page is the view, controller is the controller, sObject is the model.
Server-side rendering and the postback cycle
Visualforce is server-rendered. Every interaction (button click, picklist change, form submit) usually involves a full page postback to the server, which re-renders the entire page or a re-rendered section. This is fundamentally different from LWC, which runs in the browser and makes targeted API calls. The postback cycle adds latency to every interaction and produces the classic "full page flash" UX that distinguishes Visualforce from modern single-page interfaces. AJAX-style partial re-render via apex:actionFunction reduces but does not eliminate the latency.
Where Visualforce still shines
Despite deprecation pressure, several use cases remain Visualforce-territory. Email Templates with merge fields against sObjects render Visualforce well. PDF rendering via the renderAs="pdf" attribute lets pages output formatted PDFs for invoices, contracts, and reports; LWC has no equivalent server-side PDF capability. Salesforce Sites pages for public-facing content sometimes still use Visualforce because of simpler authentication and templating. Mass action overrides on standard objects can be Visualforce-based for behaviors that custom Lightning quick actions cannot match.
Lightning Experience compatibility and iframe wrapping
Visualforce Pages run in Lightning Experience inside an iframe wrapper. This works for most legacy pages but introduces limitations: visual styling differs from the surrounding Lightning UI, navigation between Visualforce pages can confuse Lightning's history management, and inter-frame communication uses sforce.one.navigate. The iframe wrapping also means Visualforce performance does not benefit from Lightning's caching layers. For native Lightning UX, LWC is the only path.
Common Visualforce patterns and tags
apex:page is the root tag. apex:form wraps a postback-capable form. apex:inputField and apex:outputField bind to sObject fields with metadata-aware rendering. apex:pageBlock and apex:pageBlockSection produce the classic Salesforce visual grouping. apex:commandButton triggers a controller action. apex:repeat iterates a collection. apex:actionFunction lets JavaScript invoke a controller method. The tag library is large and powerful but the learning curve is real because the rendering rules and postback semantics are unique to Visualforce.
Migration patterns to Lightning Web Components
Three patterns dominate Visualforce-to-LWC migration. Rebuild from scratch: design the modern UX with LWC ground-up, accepting that the legacy UX cannot be mirrored exactly. Embed Visualforce in Lightning page: keep the Visualforce Page and embed it in a Lightning record page via the visualforcePage standard component, which buys time without rebuilding. Hybrid co-existence: build new functionality as LWC while leaving legacy Visualforce Pages in place, slowly migrating screen-by-screen. Each pattern trades migration cost against modernization speed.
Performance, caching, and the view state
Visualforce maintains a view state on the server for each rendered page. The view state preserves controller state across postbacks but consumes memory and bandwidth. Large view states (over 170 KB) cause performance warnings; the platform limits view state per page. Caching with the cache="true" attribute caches page output for unauthenticated requests, useful for Sites pages. Performance tuning Visualforce often comes down to view state hygiene: don't store more in the controller than the next postback needs.
How to create a Visualforce Page
Building a Visualforce Page is mechanically simple but produces output that increasingly feels dated next to Lightning UI. Use Visualforce for the specific use cases where it still shines (email templates, PDF rendering, certain Sites pages). For everything else, build LWC components instead. The instructions below cover the realistic activities for any team that still maintains or extends Visualforce.
- Confirm Visualforce is the right tool for the use case
PDF rendering, email templates, and certain Sites pages still warrant Visualforce. Everything else should be Lightning Web Components. If the page is a new record-detail experience, build LWC instead and skip Visualforce.
- Create the page via Setup or VS Code
Setup > Visualforce Pages > New. Or in VS Code with the Salesforce Extensions Pack, create a .page file under force-app/main/default/pages/. The file extension and metadata file (.page-meta.xml) make it deployable.
- Set the page attributes on apex:page
Specify standardController or controller, renderAs for PDF output, showHeader, sidebar, and tabStyle for visual integration. Lightning Experience compatibility requires checking the Available for Lightning Experience checkbox in the page metadata.
- Add Visualforce tags and HTML markup
Use apex:form to wrap input controls. apex:pageBlock for visual grouping. apex:inputField and apex:outputField for sObject-bound fields. apex:commandButton to trigger controller actions. Standard HTML tags work alongside Visualforce tags.
- Build the Apex controller
Custom controller for fully custom logic. Controller extension for adding methods to a standard controller. Each controller method returns a PageReference (for navigation) or void (for stay-on-page action). Mark methods @AuraEnabled if also calling from LWC.
- Test in sandbox with realistic data
Verify the page renders, postbacks work, view state stays small, and the rendered output matches design. Test on different profiles to catch FLS issues. Test in both Lightning Experience (iframe-wrapped) and any Sites context.
- Assign profile access
Setup > Visualforce Pages > the page > Security. Add profiles that should have access. Without access, users see a permission error when they navigate to the page.
- Deploy via change set, metadata API, or SFDX
Bundle the page, metadata file, and controller together. Run a test deployment in sandbox before promoting to production. Verify performance against production data volumes because Visualforce view state can balloon on large record sets.
Standard for one-sObject CRUD with auto-generated methods. Extension to add custom methods on top of standard. Custom for entirely custom logic.
Default is HTML. renderAs=pdf produces a server-rendered PDF, useful for invoices, contracts, and printable reports. No LWC equivalent for PDF rendering.
Available for Lightning Experience checkbox. Required for the page to appear in Lightning context (where it renders inside an iframe wrapper).
- Visualforce is supported but no longer the strategic direction. New custom UI should be Lightning Web Components. Every new Visualforce page becomes a future migration target.
- Lightning Experience wraps Visualforce in an iframe. Visual styling differs from the surrounding Lightning UI, and inter-frame navigation requires sforce.one.navigate instead of standard window.location.
- View state grows with the data the controller holds across postbacks. Large view states (over 170 KB) trigger warnings and degrade performance. Keep controllers lean by reloading data per postback when possible.
- PDF rendering via renderAs=pdf has its own gotchas: limited CSS support, no JavaScript execution, fixed page sizes. Build PDF pages with simple markup and test the rendered output carefully.
- Profile assignment is required even if the user has Apex class access. Visualforce Pages need explicit profile-level access; without it, users see a permission error.
Trust & references
Cross-checked against the following references.
- Visualforce Developer GuideSalesforce Developer
- Visualforce Component ReferenceSalesforce Developer
- Visualforce View StateSalesforce Developer
Straight from the source - Salesforce's reference material on Visualforce Page.
- Visualforce Quick StartSalesforce Developer
- Visualforce ControllersSalesforce Developer
- Render Visualforce as PDFSalesforce Developer
About the Author
Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.
Test your knowledge
Q1. What is a Visualforce Page?
Q2. Is it still the recommended approach?
Q3. Where is Visualforce still the right choice?
Discussion
Loading discussion…