Skip to content

App Caching

Every application gets its own isolated key-value cache, accessible from business rules via the Cache global object. Use it for rate limiting, memoizing expensive computations, or sharing state between rule executions.

// Store a value (TTL optional)
Cache.set(key, value, ttl);
// Retrieve a value (null if not found or expired)
Cache.get(key);
// Delete a key
Cache.delete(key);
// Clear all keys in this app's namespace
Cache.clear();
// List keys (with optional prefix pattern)
Cache.keys(pattern);
Cache.set('key', 'value', '5m'); // 5 minutes
Cache.set('key', 'value', '1h'); // 1 hour
Cache.set('key', 'value', 300); // 300 seconds
Cache.set('key', 'value'); // Default TTL (5 minutes)

Cache stores any JSON-serializable value: strings, numbers, booleans, arrays, objects.

Cache.set('count', 42);
Cache.set('config', { threshold: 100, enabled: true });
Cache.set('tags', ['urgent', 'customer']);

Caches are namespaced per application. A CRM rule cannot read the HR app’s cache, and vice versa. This is enforced automatically.

const key = 'api_calls_' + record.user_id;
const count = Cache.get(key) || 0;
if (count >= 100) {
throw new Error('Rate limit exceeded: max 100 requests per minute');
}
Cache.set(key, count + 1, '1m');
const cacheKey = 'monthly_stats_' + record.department_id;
let stats = Cache.get(cacheKey);
if (stats === null) {
// Expensive query
const records = list('transactions', {
filter: 'and(eq(department_id, "' + record.department_id + '"), gte(date, "2025-01-01"))',
limit: 10000
});
stats = {
total: records.reduce((sum, r) => sum + r.amount, 0),
count: records.length
};
Cache.set(cacheKey, stats, '30m');
}
record.monthly_total = stats.total;
const dedupeKey = 'processed_' + record.external_id;
if (Cache.get(dedupeKey)) {
throw new Error('Duplicate submission');
}
Cache.set(dedupeKey, true, '1h');
SettingDefault
Max keys per app1,000
Default TTL5 minutes
BackendIn-memory or distributed (ValKey)
Eviction policyW-TinyLFU (adaptive frequency/recency)

Superusers can inspect cache stats — hit rate, size, and eviction counts — via the superuser-only API:

GET /api/internal/caches/stats

With the distributed cache enabled, the app cache is shared across instances. Writes on one instance are visible to all others. Without it, each instance has its own in-memory cache.