top of page

    @AuraEnabled and cacheable=true in Salesforce: Complete Guide for LWC Developers

    • Writer: VlocityGru
      VlocityGru
    • 2 days ago
    • 4 min read

    Updated: 1 day ago


    Introduction

    If you are building Lightning Web Components (LWC) or working with Vlocity OmniStudio, you have likely seen @AuraEnabled on Apex methods. But what exactly does it do — and what is the difference between @AuraEnabled and @AuraEnabled(cacheable=true)?

    This guide breaks it down clearly: what each annotation means, when to use cacheable=true, what restrictions apply, and what interviewers are really asking when they bring this topic up.


    What is @AuraEnabled in Salesforce Apex?

    @AuraEnabled is an Apex annotation that exposes a method so it can be called from Lightning Web Components (LWC) or Aura components.

    apex

    @AuraEnabled
    public static Account getAccount(Id accId) {
        return [SELECT Id, Name FROM Account WHERE Id = :accId];
    }

    Without @AuraEnabled, the method is invisible to the frontend:

    Caller

    Without @AuraEnabled

    With @AuraEnabled

    LWC

    ❌ Cannot call

    ✅ Can call

    Aura Component

    ❌ Cannot call

    ✅ Can call

    OmniScript (via Apex Action)

    ❌ Cannot call

    ✅ Can call

    This annotation is the bridge between your Apex backend and your Lightning frontend. It is mandatory — no annotation, no access.


    What Does cacheable=true Mean?

    apex

    @AuraEnabled(cacheable=true)
    public static Account getAccount(Id accId) {
        return [SELECT Id, Name FROM Account WHERE Id = :accId];
    }

    Adding cacheable=true tells Salesforce:

    "The result of this method can be stored temporarily on the client side and reused."

    In practice, this means:

    • Salesforce stores the response in the client-side cache after the first call

    • If the same method is called again with the same parameters, the data may be returned from cache instead of hitting the server

    • This results in a faster UI and reduced server load


    Benefits of cacheable=true


    • Faster UI rendering — no round-trip to the server on repeated calls

    • Reduced Apex execution — fewer governor limit concerns

    • Better user experience — especially on detail pages and read-heavy screens


    The Most Important Rule: cacheable=true Is Read-Only Only

    This is where most developers make mistakes.

    cacheable=true can only be used when the Apex method is completely read-only - meaning it contains no DML operations whatsoever.


    Allowed with cacheable=true ✅

    @AuraEnabled(cacheable=true)
    public static List<Contact> getContacts(Id accId) {
        return [SELECT Id, Name, Email FROM Contact WHERE AccountId = :accId];
    }

    NOT Allowed with cacheable=true ❌

    @AuraEnabled(cacheable=true)
    public static void updateAccount(Account acc) {
        update acc; // ❌ Runtime error — DML not allowed with cacheable=true
    }

    Forbidden DML operations with cacheable=true:

    • insert

    • update

    • delete

    • upsert

    • merge

    • undelete


    If you include DML in a cacheable=true method, Salesforce throws a runtime error. It will not warn you at compile time — so test carefully.


    Why cacheable=true Is Mainly Used in LWC

    LWC re-renders frequently — when reactive properties change, when data refreshes, when navigation occurs. Without caching, every re-render could trigger a fresh Apex call.

    cacheable=true is especially valuable for:


    • Detail pages — loading Account or Contact data

    • Search results — displaying filtered records

    • Lookup fields — fetching related records

    • Read-only dashboards — summarizing data


    Using cacheable=true with @wire (Recommended Pattern)

    import { LightningElement, wire } from 'lwc';
    import getAccount from '@salesforce/apex/AccountController.getAccount';
    
    export default class AccountDetail extends LightningElement {
        @wire(getAccount, { accId: '$recordId' })
        account;
    }

    @wire requires the Apex method to have cacheable=true. If you try to wire a non-cacheable method, LWC will throw an error.


    When NOT to Use cacheable=true

    Avoid cacheable=true when:

    • The data changes frequently and you need fresh results every time

    • The method performs any DML (save, update, delete)

    • The method contains validation logic before a save

    • The method is part of a form submission or transactional flow

    Using cacheable=true on methods that should return fresh data can cause stale data bugs that are very difficult to debug — the UI shows old data because it is pulling from cache.


    OmniScript and cacheable=true — A Critical Distinction


    This is a frequent interview topic for Vlocity / OmniStudio developers.


    Question: Can you use cacheable=true for Apex called from OmniScript?

    Answer: No.

    Here is why:

    OmniScript invokes Apex imperatively (not via @wire). More importantly, OmniScript flows are often transactional — they collect data across steps and submit it. In this context:

    • Cached data can become stale mid-flow

    • The user may see data from a previous session

    • Transactional integrity is compromised

    Scenario

    Use cacheable=true?

    LWC read-only data fetch

    ✅ Yes

    LWC @wire call

    ✅ Required

    LWC imperative save/update

    ❌ No

    OmniScript Apex Action

    ❌ No

    Integration Procedure Apex Step

    ❌ No


    How Salesforce Caching Works (Simplified)

    1. LWC calls an Apex method with cacheable=true

    2. Apex executes and returns the result

    3. Salesforce stores the response in the client-side Lightning Data Service cache

    4. On the next call with the same parameters, the cached response is returned

    5. The server is not contacted again (until the cache expires or is invalidated)


    Important: You do not control the cache duration directly. Salesforce manages cache expiry. You can manually refresh cache in LWC using refreshApex() when needed.

    import { refreshApex } from 'lightning/uiRecordApi';
    
    // Call this to force a fresh server call
    refreshApex(this.wiredResult);

    Interview-Ready Explanation


    If an interviewer asks about @AuraEnabled(cacheable=true), here is a clear, concise answer:

    "@AuraEnabled exposes an Apex method to LWC and Aura components. Adding cacheable=true enables client-side caching of the response, which improves performance by avoiding repeated server calls. It can only be used on read-only methods — any DML will cause a runtime error. It is required when using @wire in LWC, and should never be used with OmniScript Apex actions."

    Quick Reference: Mental Model

    cacheable=true  →  read-only + fast + @wire compatible
    no cacheable    →  write / validate / save / OmniScript

    Summary


    • @AuraEnabled is mandatory to expose Apex to LWC, Aura, or OmniScript

    • cacheable=true enables client-side caching for read-only methods

    • DML inside a cacheable=true method causes a runtime error

    • @wire in LWC requires cacheable=true

    • OmniScript Apex actions should never use cacheable=true

    • Use refreshApex() when you need to bypass cache and fetch fresh data


     
     
     

    © 2024 VlocityGru Blog. All Rights Reserved.

    bottom of page