📚 StoneJS Developer Guide

Complete reference for building modern web applications with the StoneJS Framework

⚡ Caching

Cache System

StoneJS includes a powerful built-in in-memory cache for improving application performance. The cache supports component-level caching and data caching patterns.

Cache Methods

Method Description Returns
set(key, value, ttl) Store value in cache with TTL in seconds void
get(key) Retrieve cached value by key value or undefined
delete(key) Remove specific key from cache void
has(key) Check if key exists in cache boolean
clear() Remove all cached items void
remember(key, ttl, fn) Cache result of async function (most useful) Promise<value>
cacheSelf(options) Cache entire component output (Mason-style) Promise<boolean>
getStats() Get cache statistics {hits, misses, hitRate, size}

Basic Cache Operations

<%%js> // Set cache with 5 minute TTL $cache.set('user-data', userData, 300); // Get cached value const cached = $cache.get('user-data'); // Check if exists if ($cache.has('user-data')) { console.log('Cache hit!'); } // Delete specific key $cache.delete('user-data'); // Clear all cache $cache.clear();

Remember Pattern (Recommended)

The remember() method is the most elegant caching pattern. It automatically handles cache misses by executing your function and storing the result.

✅ How it works: If the key exists in cache, return cached value. Otherwise, execute the function, cache the result, and return it.

Example: Database Query Caching

<%%js> // Cache database query for 5 minutes (300 seconds) const users = await $cache.remember('all-users', 300, async () => { console.log('Cache miss - fetching from database'); return await $db.query('SELECT * FROM users WHERE active = $1', [true]); }); // First call: executes query, caches result // Subsequent calls: returns cached data instantly

Example: External API Caching

<%%js> // Cache weather API response for 10 minutes const weatherData = await $cache.remember('weather-nyc', 600, async () => { const response = await fetch('https://api.weather.com/v1/nyc'); return await response.json(); });

Example: User-Specific Caching

<%%js> // Use dynamic cache keys for per-user data const userId = $session.userId; const cacheKey = `user-profile-${userId}`; const profile = await $cache.remember(cacheKey, 300, async () => { const result = await $db.query( 'SELECT * FROM profiles WHERE user_id = $1', [userId] ); return result[0]; });

💡 Pro Tip: Use prefixes in cache keys to organize related data: user-profile-123, api-weather-nyc, db-all-users

Component Caching (cacheSelf)

Cache entire page/component output with Mason-style cacheSelf() method:

<%%init> // Cache this entire component for 1 hour if (await $cache.cacheSelf({ expiresIn: '1 hour', busyLock: '10 sec' })) { return; // Cached version served } // This code only runs on cache miss const expensiveData = await fetchExpensiveData();

💡 Learn More: See the complete cache documentation for cacheSelf() options, busy lock patterns, and advanced examples.

Cache Invalidation

When data changes, invalidate related cached entries to ensure freshness:

<%%js> // Update user data if ($req.method === 'POST') { await $db.query( 'UPDATE users SET name = $1 WHERE id = $2', [$req.body.name, userId] ); // Invalidate affected cache entries $cache.delete(`user-profile-${userId}`); $cache.delete('all-users'); $context.set('success', 'Profile updated'); }

⚠️ Cache Invalidation Strategy: Delete all cache keys affected by data changes. Missing an invalidation can show stale data to users.

Cache Statistics

Monitor cache performance with built-in statistics:

<%%js> // Get detailed cache statistics const stats = $cache.getStats(); // Returns: { hits, misses, hitRate, size } console.log(`Cache hit rate: ${(stats.hitRate * 100).toFixed(1)}%`); console.log(`Cache size: ${stats.size} items`);
Statistic Description
hits Number of successful cache lookups
misses Number of cache misses (had to fetch data)
hitRate Percentage of requests served from cache (0-1)
size Current number of cached items

Best Practices

  • Use remember() pattern for expensive operations
  • Set appropriate TTL based on data freshness needs
  • Use descriptive cache keys (prefix with context)
  • Invalidate cache when underlying data changes
  • Monitor cache hit rates in production
  • Don't cache user-specific data with shared keys

REST APIs → Cache Demo

Need more help?

View All Demos Getting Started GitHub Repository