Size Limits and Best Practices for Using CacheManager in Jira Data Center Plugins

Hi Community,

I’m trying to implement Cache using Atlassian’s CacheManager (Atlassian Cache - API 2.9.0 API) to cache common/global user-level settings. I have several questions around cache limits and expiration that I’d appreciate some clarification on (specific to Jira Data Center):


Specific Questions:

  1. Size Limits

    • Is there a maximum size limit for a cache or a cached value?
      For example:
      • Is a total cache size like 8MB(example) enforced anywhere internally?
      • Can a single cached value (e.g., a long JSON string or object) be several hundred KB or even a few MB?
    • Can I safely cache thousands of user entries in a List (containing usernames)?
  2. Expiration Policy

    • Is it mandatory to set an expiration policy?
    • What happens if I don’t set any expiry?
      I’m considering managing the cache manually using get() and put() when the DB is updated or reinitialize it on Server restart.
    • Are there recommended TTL values for plugin-level caching?

Sample Code:

package com.example.helloworld.cache;

import com.atlassian.cache.Cache;
import com.atlassian.cache.CacheLoader;
import com.atlassian.cache.CacheManager;
import com.atlassian.cache.CacheSettings;
import com.atlassian.cache.CacheSettingsBuilder;
import com.atlassian.sal.api.pluginsettings.PluginSettings;
import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;

public class HelloWorldCacheManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldCacheManager.class);

    private static final String DB_KEY_HELLO_NAME = "com.example.helloworld.HELLO_NAME";
    private static final String CACHE_KEY_HELLO_NAME = "hello-name";

    private final PluginSettingsFactory pluginSettingsFactory;
    private final CacheManager cacheManager;

    private static volatile Cache<String, String> helloNameCache;

    @Inject
    public HelloWorldCacheManager(PluginSettingsFactory pluginSettingsFactory, CacheManager cacheManager) {
        this.pluginSettingsFactory = pluginSettingsFactory;
        this.cacheManager = cacheManager;
    }

    /**
     * Initializes the cache lazily and thread-safely.
     */
    public Cache<String, String> getCache() {
        if (helloNameCache == null) {
            synchronized (HelloWorldCacheManager.class) {
                if (helloNameCache == null) {
                    LOGGER.debug(">>> Initializing helloNameCache");

                    CacheSettings cacheSettings = new CacheSettingsBuilder()
                            .remote()
                            .replicateViaInvalidation()
                            .build();

                    helloNameCache = cacheManager.getCache(
                            "com.example.helloworld:name-cache",
                            new CacheLoader<String, String>() {
                                @Override
                                public String load(String key) {
                                    LOGGER.debug(">>> Cache miss - Loading from DB via PluginSettings");
                                    PluginSettings settings = pluginSettingsFactory.createGlobalSettings();
                                    String value = (String) settings.get(DB_KEY_HELLO_NAME);
                                    return value != null ? value : "World";
                                }
                            },
                            cacheSettings
                    );
                }
            }
        }
        return helloNameCache;
    }

    /**
     * Retrieves the name from cache, or DB if not cached.
     */
    public String getHelloName() {
        Cache<String, String> cache = getCache();
        String value = cache.get(CACHE_KEY_HELLO_NAME);
        LOGGER.debug(">>> Retrieved 'HELLO_NAME' = {}", value);
        return value;
    }

    /**
     * Updates both the cache and DB.
     */
    public void setHelloName(String value) {
        PluginSettings settings = pluginSettingsFactory.createGlobalSettings();
        settings.put(DB_KEY_HELLO_NAME, value);
        getCache().put(CACHE_KEY_HELLO_NAME, value);
        LOGGER.debug(">>> Updated 'HELLO_NAME' to value: {}", value);
    }

    /**
     * Updates the cache only (no DB update).
     */
    public void updateHelloNameCacheOnly(String value) {
        getCache().put(CACHE_KEY_HELLO_NAME, value);
        LOGGER.debug(">>> Updated 'HELLO_NAME' in cache only to value: {}", value);
    }

    /**
     * Clears the cached name value.
     */
    public void clearHelloNameCache() {
        getCache().remove(CACHE_KEY_HELLO_NAME);
        LOGGER.debug(">>> Cleared cache for 'HELLO_NAME'");
    }
}

Any guidance or references to documentation would be greatly appreciated!

Thanks!