The short version: JavaScript remoting is a way to call a static Apex method from a Visualforce page without a postback and without view state, and Remote Objects is a declarative way to do basic record CRUD from JavaScript with no Apex at all. Both still work and neither is getting attention. For anything new, Lightning Web Components with wire adapters and @AuraEnabled Apex do the same job better. The reason to know these is that plenty of orgs still run them, and somebody has to maintain that code.
JavaScript remoting, in shape
Mark a static method @RemoteAction and call it from the page’s JavaScript with a generated proxy.
global with sharing class AccountRemoter {
@RemoteAction
global static List<Account> search(String term) {
String like = '%' + String.escapeSingleQuotes(term) + '%';
return [
SELECT Id, Name, Industry FROM Account
WHERE Name LIKE :like WITH USER_MODE LIMIT 25
];
}
}
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.AccountRemoter.search}',
term,
function (result, event) {
if (event.status) {
render(result);
} else {
console.error(event.message);
}
},
{ escape: true, timeout: 30000 }
);
The method must be static. It gets no access to page controller state, so everything it needs comes in as arguments. The callback receives the deserialised return value and an event object whose status is false when Apex threw.
The advantage over apex:actionFunction is the one that mattered: no view state. A remoting call sends only its arguments and receives only its return value, where an action function round trips the entire serialised page state. On a complex page that is the difference between a snappy control and a two second pause.
The escape option defaults to true and HTML escapes the response. Turning it off because your markup looked wrong is how remoting pages get cross site scripting holes. Fix the rendering instead.
Remote Objects
Remote Objects gave you create, read, update and delete from JavaScript with declarative markup and no Apex class.
<apex:remoteObjects>
<apex:remoteObjectModel name="Account" fields="Id,Name,Industry">
<apex:remoteObjectField name="AnnualRevenue" jsShorthand="revenue"/>
</apex:remoteObjectModel>
</apex:remoteObjects>
Its selling point was that the generated calls respect sharing and field level security automatically, and do not consume API request allocation. Its limitation was that it only did simple record operations. Anything involving a join, a calculation or a rule went back to Apex, which is most things, so the feature never displaced remoting.
What replaced them
Lightning Web Components cover the same ground with less ceremony.
- Instead of Remote Objects, the wire adapters in
lightning/uiRecordApi:getRecord,createRecord,updateRecord,deleteRecord. Same no Apex promise, same automatic security, plus a cache that keeps components in sync when a record changes elsewhere on the page. - Instead of remoting, an imperative or wired call to an
@AuraEnabledApex method. You get the same static method model, withcacheable=trueavailable for read only calls. - For multi object reads, the GraphQL wire adapter, which fetches related data in one request.
The practical differences favour LWC. @AuraEnabled methods do not have to be global. Errors come back as structured objects rather than a message string. The framework handles caching and refresh. And the component is reusable on a record page, a Flow screen, an app page and a community without being rewritten.
Where Visualforce is still the right answer
Visualforce is supported and is not going away, and a handful of jobs still belong to it.
- PDF generation.
renderAs="pdf"has no LWC equivalent. Quote documents and printable reports are still built this way. - Email templates that need real logic in the markup.
- Classic overrides and buttons in orgs that have not migrated.
- Pages that already exist and work. Rewriting a functioning remoting page in LWC buys you nothing a user will notice.
A Visualforce page embedded in Lightning Experience runs in an iframe, which affects navigation, styling and anything that assumes it owns the window. If you are keeping a page, keep it in a place where that constraint is acceptable.
Maintaining remoting code you inherited
Three checks are worth running on any remoting class you touch. Does it enforce sharing, given that @RemoteAction methods are static and the class declaration is the only place that is decided. Does it use WITH USER_MODE on its queries, since WITH SECURITY_ENFORCED is no longer supported. And is escape still on.
Remoting methods are also a public surface in a way a page controller is not, so treat every argument as untrusted input and bind or validate it accordingly.
Frequently asked
Do remoting calls count against the API limit? No. They are page requests, not API requests, which is one reason high traffic Sites pages used them.
Can a remoting method be with sharing? The class can be, and that governs the method. Since the method is static and global, be explicit in the class declaration rather than relying on the default.
Is Remote Objects deprecated? Not formally removed, but it has had no meaningful investment for years. Do not start anything new with it.
Should I migrate a working remoting page? Only when you are changing it anyway, or when it needs to appear somewhere Visualforce cannot go. A rewrite with no user visible benefit is hard to justify and easy to get wrong.
