agentsclimarketplace

Cache integration

Skill ColdBox/skills/coldbox/cache-integration

Collection of skills for the ColdBox Platform and Claude Plugin

Install
npx -y skills add ColdBox/skills --skill cache-integration

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use this skill when implementing caching inside a ColdBox application -- configuring CacheBox via ColdBox.cfc or config/CacheBox.cfc, injecting caches with WireBox (cachebox:name), using getCache() in handlers, event/view output caching with setEventCacheableEntry(), view fragment caching with renderView(cache=true), query caching, cache listeners as ColdBox interceptors, Redis/distributed provider setup, or choosing between default and template caches.

SKILL.md

21.1 KB, ~4.7k tokens by cl100k_base, as published. Nobody here has run it

CacheBox — ColdBox Integration

When to Use This Skill

Use this skill when adding caching to a ColdBox application. For standalone CacheBox usage (no ColdBox framework), see the cachebox-standalone skill.

Language Mode Reference

Examples use BoxLang (.bx) syntax by default. For CFML replace class with component and use property name="x" inject="y"; annotations.

ConceptBoxLangCFML
Classclass {component {
WireBox inject annotation@inject( "dsl" ) above propertyproperty name="x" inject="dsl";
View files.bxm.cfm

1. How ColdBox Wires CacheBox

ColdBox creates and manages a CacheBox factory automatically. No Application.cfc bootstrap code is needed. The factory is accessible via:

// From any handler, interceptor, or service
var cacheBox  = getCacheBox();          // the CacheBox factory
var defCache  = getCache();             // default cache provider
var tplCache  = getCache( "template" ); // named cache provider

2. Configuration

ColdBox looks for CacheBox config in this order:

  1. cachebox DSL struct inside config/ColdBox.cfcconfigure()
  2. config/CacheBox.cfc (portable CFC by convention — recommended)
  3. Built-in defaults at coldbox/system/web/config/CacheBox.cfc

2a. Default built-in caches (no config required)

ColdBox ships with two built-in caches:

Cache nameObject storePurpose
defaultConcurrentStore (guaranteed)General data, objects, query results
templateConcurrentSoftReferenceStore (memory-sensitive)Event output caching, view fragment caching

Use the defaults until you need different TTLs, size limits, or distributed providers.

2b. config/CacheBox.cfc (recommended for custom config)

// config/CacheBox.cfc
component {

    function configure() {
        cacheBox = {
            // All timeouts in MINUTES

            // MANDATORY. "default" is reserved. coldboxEnabled MUST be true in ColdBox apps.
            defaultCache : {
                objectDefaultTimeout           : 60,
                objectDefaultLastAccessTimeout : 30,
                useLastAccessTimeouts          : true,
                reapFrequency                  : 2,
                freeMemoryPercentageThreshold  : 0,
                evictionPolicy                 : "LRU",
                evictCount                     : 1,
                maxObjects                     : 300,
                objectStore                    : "ConcurrentStore",
                coldboxEnabled                 : true  // REQUIRED for ColdBox
            },

            caches : {
                // ColdBox event/view template caching — memory-sensitive is appropriate here
                template : {
                    provider   : "coldbox.system.cache.providers.CacheBoxColdBoxProvider",
                    properties : {
                        objectDefaultTimeout           : 60,
                        objectDefaultLastAccessTimeout : 30,
                        useLastAccessTimeouts          : true,
                        reapFrequency                  : 2,
                        freeMemoryPercentageThreshold  : 0,
                        evictionPolicy                 : "LRU",
                        evictCount                     : 2,
                        maxObjects                     : 300,
                        objectStore                    : "ConcurrentSoftReferenceStore"
                    }
                },

                // Product catalog — long TTL, guaranteed objects
                products : {
                    provider   : "coldbox.system.cache.providers.CacheBoxColdBoxProvider",
                    properties : {
                        objectDefaultTimeout : 240,   // 4 hours
                        maxObjects           : 1000,
                        objectStore          : "ConcurrentStore"
                    }
                },

                // Session/token cache — match your session timeout
                sessions : {
                    provider   : "coldbox.system.cache.providers.CacheBoxColdBoxProvider",
                    properties : {
                        objectDefaultTimeout : 30,
                        maxObjects           : 5000,
                        objectStore          : "ConcurrentStore"
                    }
                }
            }
        };
    }
}

2c. Inline DSL inside ColdBox.cfc

// config/ColdBox.cfc
function configure() {
    // ...other config...

    // Option A: point to an external CFC
    cacheBox = { configFile : "config.CacheBox" };

    // Option B: inline DSL  (same keys as portable CFC above)
    cacheBox = {
        defaultCache : { objectDefaultTimeout : 60, maxObjects : 300, coldboxEnabled : true },
        caches       : {}
    };
}

2d. Engine-native providers (Lucee / Adobe CF caches)

// config/CacheBox.cfc  — add after the default caches block
if ( listFindNoCase( "Lucee", server.coldfusion.productname ) ) {
    cacheBox.caches.luceeCache = {
        provider : "coldbox.system.cache.providers.LuceeColdBoxProvider"
    };
} else {
    cacheBox.caches.cfCache = {
        provider : "coldbox.system.cache.providers.CFColdBoxProvider"
    };
}

2e. Redis provider (cbRedis module)

box install cbRedis
// config/CacheBox.cfc
caches : {
    redis : {
        provider   : "cbRedis.models.providers.RedisProvider",
        properties : {
            host                 : getSystemSetting( "REDIS_HOST", "localhost" ),
            port                 : getSystemSetting( "REDIS_PORT", 6379 ),
            password             : getSystemSetting( "REDIS_PASSWORD", "" ),
            database             : 0,
            objectDefaultTimeout : 60,
            keyPrefix            : "myapp:"
        }
    },
    // Distribute sessions across cluster nodes
    sessions : {
        provider   : "cbRedis.models.providers.RedisProvider",
        properties : {
            host                 : getSystemSetting( "REDIS_HOST", "localhost" ),
            port                 : getSystemSetting( "REDIS_PORT", 6379 ),
            objectDefaultTimeout : 30,
            keyPrefix            : "myapp:session:"
        }
    }
}

3. Injecting Caches with WireBox

Use WireBox DSL to inject cache providers into any managed component (services, handlers, interceptors).

BoxLang:

class ProductService {

    // Inject by name — resolves to the named cache provider
    @inject( "cachebox:default" )
    property name="cache";

    @inject( "cachebox:products" )
    property name="productCache";

    @inject( "cachebox:template" )
    property name="templateCache";

    // Inject the full CacheBox factory (to resolve caches dynamically)
    @inject( "cachebox" )
    property name="cacheBox";

    function getCacheByName( required string name ) {
        return cacheBox.getCache( name )
    }
}

CFML:

component {

    property name="cache"         inject="cachebox:default";
    property name="productCache"  inject="cachebox:products";
    property name="templateCache" inject="cachebox:template";
    property name="cacheBox"      inject="cachebox";
}

From handlers/interceptors (no injection needed)

// Available directly in handlers and interceptors via controller helpers
var cache    = getCache();             // default cache
var tpl      = getCache( "template" );
var cacheBox = getCacheBox();

4. Core Cache API (Same for All Providers)

All timeouts are in minutes.

// ── WRITE ────────────────────────────────────────────────────────────────────
cache.set( "product_1", product, 60, 30 );   // TTL=60, idle=30
cache.set( "product_1", product );           // use configured defaults
cache.set( "config", data, 0, 0 );          // eternal

// ── READ ─────────────────────────────────────────────────────────────────────
var val = cache.get( "product_1" );          // null if missing/expired
var val = cache.getQuiet( "product_1" );    // does not reset idle timer

// ── GET-OR-SET ────────────────────────────────────────────────────────────────
var product = cache.getOrSet(
    objectKey  : "product_1",
    produce    : function() { return productRepository.findById( 1 ) },
    timeout    : 60,
    lastAccess : 30
);

// ── CHECK ────────────────────────────────────────────────────────────────────
var exists = cache.lookup( "product_1" );
var exists = cache.lookupQuiet( "product_1" ); // no idle reset

// ── DELETE ───────────────────────────────────────────────────────────────────
cache.clear( "product_1" );
cache.clearByKeySnippet( "product_", false );        // all keys containing snippet
cache.clearByKeySnippet( "^product_\d+$", true );   // regex
cache.clearAll();
cache.expireObject( "product_1" );    // lazy expire

// ── INSPECT ──────────────────────────────────────────────────────────────────
var meta  = cache.getCachedObjectMetadata( "product_1" );
var keys  = cache.getKeys();
var size  = cache.getSize();
var stats = cache.getStats();

5. Service-Layer Cache Patterns

Simple cache-aside

BoxLang:

class ProductService {

    @inject( "cachebox:products" )
    property name="cache";

    function getById( required numeric id ) {
        var key     = "product_#id#"
        var product = cache.get( key )

        if ( !isNull( product ) ) {
            return product
        }

        product = productRepository.findById( id )
        cache.set( key, product, 60, 30 )
        return product
    }

    function list( numeric page = 1, numeric limit = 25 ) {
        return cache.getOrSet(
            objectKey  : "products_list_#page#_#limit#",
            produce    : function() { return productRepository.list( page = page, limit = limit ) },
            timeout    : 30,
            lastAccess : 15
        )
    }

    function save( required struct product ) {
        var saved = productRepository.save( product )
        // Write-through
        cache.set( "product_#saved.id#", saved, 60, 30 )
        // Invalidate related list caches
        cache.clearByKeySnippet( "products_list_" )
        return saved
    }

    function delete( required numeric id ) {
        productRepository.delete( id )
        cache.clear( "product_#id#" )
        cache.clearByKeySnippet( "products_list_" )
    }
}

CFML:

component {

    property name="cache" inject="cachebox:products";

    function getById( required numeric id ) {
        return cache.getOrSet(
            objectKey  : "product_#id#",
            produce    : function() { return productRepository.findById( id ) },
            timeout    : 60,
            lastAccess : 30
        )
    }
}

Stampede protection

function getExpensiveValue( required string key, required any loader, numeric timeout = 60 ) {
    var value = cache.get( key )
    if ( !isNull( value ) ) { return value }

    lock name="cache_load_#key#" timeout="15" throwontimeout="false" type="exclusive" {
        value = cache.get( key )
        if ( isNull( value ) ) {
            value = loader()
            cache.set( key, value, timeout )
        }
    }
    return value
}

6. Event Output Caching

Cache the entire output of a handler event. ColdBox stores the rendered HTML in the template cache provider.

BoxLang:

class Catalog extends coldbox.system.EventHandler {

    function index( event, rc, prc ) {
        // Cache this event's output for 60 min, idle 30 min
        event.setEventCacheableEntry(
            provider   : "template",
            timeout    : 60,
            lastAccess : 30
        )
        prc.categories = categoryService.list()
        event.setView( "catalog/index" )
    }

    function show( event, rc, prc ) {
        // Cache per product ID — different cache entry per suffix
        event.setEventCacheableEntry(
            provider   : "template",
            timeout    : 120,
            lastAccess : 60,
            suffix     : rc.id ?: "0"
        )
        prc.product = productService.getById( rc.id ?: 0 )
        event.setView( "catalog/show" )
    }
}

CFML:

component extends="coldbox.system.EventHandler" {

    function index( event, rc, prc ) {
        event.setEventCacheableEntry(
            provider   : "template",
            timeout    : 60,
            lastAccess : 30
        )
        prc.categories = categoryService.list()
        event.setView( "catalog/index" )
    }
}

Invalidation: Event caches are keyed by event name + suffix. Clear them via getCache( "template" ).clearByKeySnippet( "event_name" ) or getCache( "template" ).clearAll().


7. View Fragment Caching

Cache individual view fragments inside a layout or view template. Uses the template cache.

// In a view or layout file (.bxm / .cfm)
#renderView(
    view                    = "shared/featured_products",
    cache                   = true,
    cacheTimeout            = 30,
    cacheLastAccessTimeout  = 15
)#

Fragment cache keys are auto-generated from the view path. Clear a fragment:

getCache( "template" ).clearByKeySnippet( "shared/featured_products" )

8. Query Caching (native CFML)

ColdFusion/Lucee/BoxLang natively cache queries with cachedWithin:

function getTopProducts() {
    return queryExecute(
        "SELECT * FROM products WHERE active = 1 ORDER BY views DESC LIMIT 10",
        {},
        {
            cachedWithin : createTimeSpan( 0, 0, 30, 0 ), // 30 minutes
            datasource   : "myapp"
        }
    )
}

Use CacheBox provider caching (not query-level) when you need explicit invalidation control.


9. Cache Listeners as ColdBox Interceptors

In ColdBox, CacheBox listeners are ColdBox interceptors — declare them in config/ColdBox.cfc.

BoxLang:

// interceptors/CacheAuditInterceptor.bx
class CacheAuditInterceptor extends coldbox.system.Interceptor {

    function configure() {}

    // ── CacheBoxProvider events ───────────────────────────────────────────
    function afterCacheElementInsert( event, interceptData, buffer ) {
        log.debug(
            "CACHE INSERT [#interceptData.cache.getName()#] #interceptData.cacheObjectKey# ttl=#interceptData.cacheObjectTimeout#"
        )
    }

    function afterCacheElementRemoved( event, interceptData, buffer ) {
        log.debug(
            "CACHE REMOVE [#interceptData.cache.getName()#] #interceptData.cacheObjectKey#"
        )
    }

    function afterCacheElementExpired( event, interceptData, buffer ) {
        log.debug(
            "CACHE EXPIRE [#interceptData.cache.getName()#] #interceptData.cacheObjectKey#"
        )
    }

    // ── CacheFactory events ───────────────────────────────────────────────
    function afterCacheFactoryConfiguration( event, interceptData, buffer ) {
        log.info( "CacheBox configured" )
        // Good place to warm caches
        warmCriticalCaches()
    }

    function beforeCacheFactoryShutdown( event, interceptData, buffer ) {
        log.warn( "CacheBox shutting down" )
    }

    private function warmCriticalCaches() {
        var cache    = getCacheBox().getCache( "products" )
        var products = productGatewayInstance.findAllActive()
        for ( var p in products ) {
            cache.set( "product_#p.id#", p, 240, 60 )
        }
    }
}

CFML:

component extends="coldbox.system.Interceptor" {

    function configure() {}

    function afterCacheElementInsert( event, interceptData, buffer ) {
        log.debug( "INSERT [#interceptData.cache.getName()#] #interceptData.cacheObjectKey#" )
    }

    function afterCacheFactoryConfiguration( event, interceptData, buffer ) {
        // Warm critical caches after CacheBox starts
    }
}

Register in config/ColdBox.cfc:

interceptors = [
    { class : "interceptors.CacheAuditInterceptor", name : "CacheAuditInterceptor", properties : {} }
];

10. CacheBox Events Available to Interceptors

CacheFactory events

EventinterceptData keys
afterCacheFactoryConfigurationcacheFactory
beforeCacheFactoryShutdowncacheFactory
afterCacheFactoryShutdowncacheFactory
afterCacheRegistrationcache
beforeCacheRemovalcache
afterCacheRemovalcache (name string)
beforeCacheReplacementoldCache, newCache
beforeCacheShutdowncache
afterCacheShutdowncache

CacheBoxProvider events

EventinterceptData keys
afterCacheElementInsertcache, cacheObject, cacheObjectKey, cacheObjectTimeout, cacheObjectLastAccessTimeout
afterCacheElementUpdatedcache, cacheNewObject, cacheOldObject
afterCacheElementRemovedcache, cacheObjectKey
afterCacheElementExpiredcache, cacheObjectKey
afterCacheClearAllcache

11. Named Cache Configuration Reference

defaultCache properties

PropertyTypeDefaultDescription
objectDefaultTimeoutnumeric60Object lifespan (minutes); 0 = eternal
objectDefaultLastAccessTimeoutnumeric30Idle timeout (minutes)
useLastAccessTimeoutsbooleantrueEnable/disable idle timeout
reapFrequencynumeric2Minutes between expiry sweeps
freeMemoryPercentageThresholdnumeric0Min JVM free memory % before caching (0=unlimited)
evictionPolicystringLRULRU, LFU, FIFO, LIFO, or custom path
evictCountnumeric1Objects evicted per policy execution
maxObjectsnumeric300Maximum live objects
objectStorestringConcurrentStoreConcurrentStore, ConcurrentSoftReferenceStore, DiskStore, JDBCStore
coldboxEnabledbooleantrueMust be true for ColdBox default cache
resetTimeoutOnAccessbooleanfalseReset TTL on each access (session-like behaviour)

12. Production Best Practices

  • Set coldboxEnabled : true in the defaultCache block — required for ColdBox app integration.
  • Use the default cache for service/data caching and the template cache exclusively for event/view output.
  • Inject caches at component level via WireBox (@inject( "cachebox:name" )) — never call getCache() inside methods if the component is a WireBox singleton.
  • Prefer getOrSet() at the service layer to eliminate null-check boilerplate.
  • Use getCache() / getCacheBox() inside handlers and interceptors — these controller helpers spare the injection overhead for one-off use.
  • Event output caching is coarse-grained — it caches entire event HTML; hard to selectively invalidate. Use only for read-heavy, infrequently updated pages.
  • View fragment caching is finer-grained than event caching — prefer it over event caching when only part of a page is static.
  • Configure Redis for multi-server / auto-scaling deployments — in-memory providers are per-process.
  • Namespace cache keys by domain and ID ("product_#id#", "user_#id#_prefs") to avoid cross-domain collisions.
  • Use clearByKeySnippet() to invalidate families of keys; avoid clearAll() which evicts everything and causes stampede.
  • Warm critical caches in the afterCacheFactoryConfiguration interceptor event — fires after ColdBox starts CacheBox.
  • Monitor getStats() per cache to tune TTL and maxObjects; low hit rates usually mean TTL is too short or keys are not reused.
  • Never cache user-specific data with a shared key — always include user identity in the cache key.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 0 of the 12 instructions most project setup skills give in ~4.7k tokens

Counted across 999 of the 1,637 authors here whose files we hold, read 2026-08-07

  • Ask one question at a timein 29 of 999, across 28 files
  • Detect the package manager from lockfilesin 28 of 999, across 9 files
  • Present findings to the userin 26 of 999, across 5 files
  • Explore current repo statein 24 of 999, across 3 files
  • Update the agent skills block in place if it existsin 24 of 999, across 3 files
  • Install husky lint-staged and prettierin 23 of 999, across 4 files
  • Create the lintstagedrc filein 22 of 999, across 3 files
  • Commit all changed filesin 22 of 999, across 3 files
  • Run lint-staged to verify it worksin 22 of 999, across 3 files
  • Create the husky pre-commit filein 21 of 999, across 2 files
  • Create a prettierrc file if missingin 21 of 999, across 2 files
  • Initialize huskyin 21 of 999, across 2 files

Said here and by no other author read

  • use built-in caches until custom configuration is required
  • set coldboxEnabled to true for default cache
  • use the template cache for event output caching
  • use ConcurrentSoftReferenceStore for template caches
  • use WireBox DSL to inject cache providers
  • use cachebox:default to inject the default cache

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 326,970. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.