Skip to main content
SFDC Developers
Apex

PlatformCache Immutable Parameter: Why It Fails

Vinay Vernekar · · 4 min read

Introduction: The PlatformCache Paradox

If you are a Salesforce developer building modular solutions or managed packages, you have likely encountered the PlatformCache namespace limitations. One of the most perplexing issues arises when using the put method within Cache.Org or Cache.Session. Specifically, the immutable parameter—designed to let us control whether cached data can be modified—often behaves in ways that defy documentation. In this guide, we will break down why this parameter is currently causing issues and how to architect your code to avoid the dreaded Cross-namespace PUT exception.

The Anatomy of the Bug

When working within a namespace, developers often attempt to set the immutable flag to false to allow for flexible data updates. The method signature part.put(key, value, ttl, visibility, immutable) suggests that by passing false to the final argument, you are explicitly telling the platform that the cached value should remain mutable.

However, in current Salesforce versions, developers are encountering a persistent runtime error:

// Attempting to use the immutable parameter
Cache.SessionPartition part = Cache.Session.getPartition('local.MyPartition');
try {
    part.put('configKey', 'someValue', 3600, Cache.Visibility.ALL, false);
} catch (Cache.Org.OrgCacheException e) {
    // Result: Failed Cache.Session.put() for key 'configKey': Cross-namespace PUT not supported
    System.debug('Error: ' + e.getMessage());
}

This is not a mistake in your logic; it is a recognized behavior identified by the Salesforce engineering team as a bug (Known Issue a02Ka00000mmTqd). Even when you set immutable to false, the platform treats the operation as an attempt to perform a cross-namespace PUT, which is restricted for security and multi-tenancy isolation reasons.

Why 'Immutable' Fails

The immutable parameter was intended to provide a mechanism to prevent race conditions or unauthorized modification of cached objects. When this flag is set, it essentially creates a 'read-only' contract for that specific cache entry.

The core of the conflict lies in the interaction between namespace boundaries and the underlying storage engine of Platform Cache. When a package tries to modify a value in a partition that the platform views as 'owned' by a different scope, it triggers a security exception. The system ignores the immutable parameter's value because the underlying restriction on cross-namespace writing is evaluated before the mutation policy is applied.

Practical Workarounds and Best Practices

Since this is an active platform bug, you cannot rely on the immutable parameter to resolve cross-namespace storage issues. Instead, you must architect your caching strategy to be namespace-agnostic or strictly self-contained.

1. Avoid Cross-Namespace Dependency

If your managed package needs to cache data, ensure that the partition is defined within your own namespace or use a common namespace that your organization controls. Do not attempt to write to partitions defined in other packages.

2. Implement a 'Get-or-Compute' Pattern

Instead of trying to force an update to an existing cache key that might belong to another scope, implement a robust 'get-or-compute' pattern that handles potential cache misses gracefully.

public static Object getCachedData(String key) {
    Cache.SessionPartition part = Cache.Session.getPartition('local.MyPartition');
    Object cachedValue = part.get(key);
    
    if (cachedValue == null) {
        // Compute the data if not in cache
        cachedValue = performComplexCalculation();
        try {
            // Use the default immutable parameter (true) to avoid the bug
            part.put(key, cachedValue, 3600);
        } catch (Exception e) {
            // Fallback for cache failure
            return cachedValue;
        }
    }
    return cachedValue;
}

3. Use Default Method Signatures

Avoid using the specific put method signature that includes the immutable parameter. By using the overloaded put methods that do not expose this flag, you bypass the logic that leads to the Cross-namespace PUT error.

Troubleshooting Checklist

  • Verify Namespace: Check if the partition you are calling resides in your package's namespace or the local namespace.
  • Check Visibility: Ensure Cache.Visibility.ALL is only used when strictly necessary. If possible, stick to Cache.Visibility.NAMESPACE to tighten security and avoid cross-scope collisions.
  • Review Known Issues: Periodically check the official Salesforce Known Issues site for updates on the ticket linked in the research section.

Key Takeaways

  • The Bug is Real: The immutable parameter in PlatformCache is currently broken for cross-namespace operations and throws a Cross-namespace PUT exception regardless of the boolean value provided.
  • Avoid the Parameter: The most effective strategy is to avoid using the overloaded put method signature containing the immutable argument altogether.
  • Design for Isolation: Cache entries should ideally be limited to your own namespace. If you must share data, use a platform event or a custom setting/object as a bridge rather than Platform Cache.
  • Use Try-Catch: Always wrap your part.put() calls in a try-catch block to ensure that a cache failure does not break your entire application logic, providing a seamless fallback for your end-users.

Share this article

Vinay Vernekar

Vinay Vernekar

Salesforce Developer & Founder

Vinay is a seasoned Salesforce developer with over a decade of experience building enterprise solutions on the Salesforce platform. He founded SFDCDevelopers.com to share practical tutorials, best practices, and career guidance with the global Salesforce community.

Get weekly Salesforce dev tutorials in your inbox

Comments

Loading comments...

Leave a Comment

Trending Now