Micro-Cache Multi-Tenant Architecture
Intelligent localStorage micro-cache with multi-tenant support and global clearing
๐ Micro-Cache Multi-Tenant Architecture
Lightning-fast localStorage caching with complete multi-tenant isolation and nuclear reset capabilities
๐ฏ Overview
The Micro-Cache system provides ultra-fast localStorage caching with:
- โก Sub-1ms Access: Fastest possible data access
- ๐ข Multi-Tenant Support: Complete namespace isolation
- โข๏ธ Nuclear Reset: Global clearing across all tenants
- ๐พ Budget Management: Automatic LRU eviction
- ๐ฏ Flash Persistence Integration: Perfect for persistent signals
๐๏ธ Architecture
Namespace-Based Isolation
localStorage Key Structure:
gg:mc:{namespace}:{key}
โโโฌโโ โโโโฌโโโ โโโโโฌโโโโ โโฌโ
โ โ โ โโ User's key
โ โ โโโโโโโโโโ Namespace (tenant/space/module)
โ โโโโโโโโโโโโโโโโโโโ Micro-cache prefix
โโโโโโโโโโโโโโโโโโโโโโโโโ GoGrab system prefix
Examples:
gg:mc:gograb-space:space_user-123- Space datagg:mc:user-456:preferences- User-specific datagg:mc:module-singularity:workflow-789- Module data
โก Core Features
1. Namespace Clearing
Clear cache for a specific namespace (tenant):
// Clear current namespace only
microCache.clear();
// Result: Clears only 'gograb-space' namespace
// Other namespaces untouched
2. User-Specific Clearing
Clear cache for a specific user across all namespaces:
// Clear all cache entries for user-123
MicroCache.clearForUser('user-123');
// Clears:
// - gg:mc:gograb-space:space_user-123
// - gg:mc:any-namespace:*user-123*
// - All entries containing 'user-123'
3. Global Nuclear Reset
Clear ALL micro-cache entries across ALL namespaces:
// Nuclear reset - clear everything
MicroCache.clearAllNamespaces();
// Clears ALL entries starting with 'gg:mc:'
// Use only for complete system resets
4. Boot Manifest Clearing
Clear boot manifests for fast hydration:
// Clear all boot manifests
BootManifestManager.clearAllNamespaces();
// Clears ALL entries starting with 'gg:boot:'
๐ Usage Examples
Basic Usage (Single Namespace)
import { MicroCache } from '@storage-system';
// Create instance for a namespace
const cache = new MicroCache('my-app', {
budget: 100 * 1024, // 100KB total
maxEntrySize: 8 * 1024, // 8KB per entry
allowLargeEntries: false
});
// Store data
cache.set('user-preferences', userPrefs);
// Retrieve data
const prefs = cache.get('user-preferences');
// Clear this namespace
cache.clear();
Multi-Tenant Usage
// Tenant A's cache
const tenantACache = new MicroCache('tenant-a');
tenantACache.set('config', { theme: 'dark' });
// Tenant B's cache
const tenantBCache = new MicroCache('tenant-b');
tenantBCache.set('config', { theme: 'light' });
// Clear only Tenant A
tenantACache.clear(); // Tenant B unaffected
// Clear specific user across all tenants
MicroCache.clearForUser('user-123'); // Clears user data everywhere
Nuclear Reset (Complete System Clear)
import { GgStorage } from '@storage-system';
// Method 1: Using GgStorage static method
GgStorage.nuclearCacheReset();
// Clears: ALL micro-cache + ALL boot manifests
// Method 2: Individual clearing
MicroCache.clearAllNamespaces(); // Clear all micro-cache
BootManifestManager.clearAllNamespaces(); // Clear all boot manifests
// Method 3: User-specific clearing
GgStorage.clearMicroCacheForUser('user-123');
๐งช Integration with Offline-First Architecture
SyncEngine Integration
The micro-cache works seamlessly with the SyncEngine:
// SyncEngine writes to IndexedDB
await syncEngine.write('space_user-123', spaceData, 'space');
// GgStorage automatically populates micro-cache
// Next read is < 1ms from micro-cache
// On nuclear reset, micro-cache is cleared
GgStorage.nuclearCacheReset();
Flash Persistence Integration
Perfect for autoFlashState:
// autoFlashState uses storage system
const theme = autoFlashState('theme', 'dark');
// Storage system uses micro-cache for hot data
// Result: < 1ms access to persistent signals
// On nuclear reset, Flash Persistence cleared
GgStorage.nuclearCacheReset();
โข๏ธ Nuclear Reset Workflow
Complete system reset procedure:
async function nuclearReset() {
// 1. Clear user context
userContextService.clearUserContext();
// 2. Clear guest sessions
await guestAuthService.clearSessions();
// 3. Clear Flash Persistence
await flashStateService.clearAllData();
// 4. Clear space data
await spaceService.clearAllData();
// 5. Clear sync queue
syncEngine.clearQueue();
// 6. Clear localStorage (preserve theme, language)
const preserve = ['theme', 'language'];
Object.keys(localStorage).forEach(key => {
if (!preserve.includes(key)) {
localStorage.removeItem(key);
}
});
// 7. Clear sessionStorage
sessionStorage.clear();
// 8. โข๏ธ NUCLEAR CACHE RESET
GgStorage.nuclearCacheReset();
// Clears ALL micro-cache + boot manifests
// 9. Clear ALL IndexedDB databases
const dbs = await indexedDB.databases();
for (const db of dbs) {
if (db.name) {
indexedDB.deleteDatabase(db.name);
}
}
// 10. Wait for cleanup
await new Promise(resolve => setTimeout(resolve, 2000));
// 11. Hard reload
window.location.href = '/landing';
}
๐ Monitoring & Debugging
Check Cache Status
// Get cache stats
const stats = microCache.getStats();
console.log({
totalSize: stats.totalSize, // Current size in bytes
entryCount: stats.entryCount, // Number of entries
hitRate: stats.hitRate, // Cache hit rate (0-1)
budgetUsed: stats.budgetUsed, // Percentage of budget used
evictions: stats.evictions // Number of evictions
});
Debug Global State
// Get all micro-cache keys across all namespaces
const allKeys = MicroCache.getAllNamespaceKeys();
console.log('All micro-cache keys:', allKeys);
// Check if cache is leaking between tenants
allKeys.forEach(key => {
console.log(key);
// Should see clear namespace separation:
// gg:mc:tenant-a:...
// gg:mc:tenant-b:...
});
๐ฏ Best Practices
1. Namespace Naming
// โ
GOOD: Clear namespace hierarchy
'gograb-space' // Main app
'tenant-acme' // Specific tenant
'user-123' // Specific user
'module-singularity' // Specific module
// โ BAD: Ambiguous namespaces
'app' // Too generic
'cache' // Not descriptive
'data' // No context
2. Budget Management
// โ
GOOD: Conservative budgets per namespace
new MicroCache('my-app', {
budget: 100 * 1024, // 100KB - reasonable
maxEntrySize: 8 * 1024, // 8KB - prevents single large entry
});
// โ BAD: Excessive budgets
new MicroCache('my-app', {
budget: 10 * 1024 * 1024, // 10MB - too large for localStorage!
maxEntrySize: 5 * 1024 * 1024, // 5MB entry - kills performance
});
3. Multi-Tenant Isolation
// โ
GOOD: Separate instances per tenant
const getTenantCache = (tenantId: string) => {
return new MicroCache(`tenant-${tenantId}`);
};
// Each tenant gets isolated cache
const acmeCache = getTenantCache('acme');
const betaCache = getTenantCache('beta');
// โ BAD: Shared cache with manual key prefixing
const cache = new MicroCache('shared');
cache.set(`tenant-acme-data`, data); // Manual isolation = error-prone
4. Nuclear Reset Safety
// โ
GOOD: Confirm before nuclear reset
if (confirm('โข๏ธ Nuclear reset? ALL data will be deleted!')) {
if (confirm('FINAL WARNING: This cannot be undone!')) {
await nuclearReset();
}
}
// โ BAD: No confirmation
await nuclearReset(); // User data lost without warning!
๐ง Configuration
Standard Configuration
const cache = new MicroCache('namespace', {
budget: 100 * 1024, // 100KB total budget
maxEntrySize: 8 * 1024, // 8KB max per entry
allowLargeEntries: false // Strict 8KB limit
});
Large Entry Support
const cache = new MicroCache('namespace', {
budget: 200 * 1024, // 200KB total budget
maxEntrySize: undefined, // Auto-calculated
allowLargeEntries: true // Allow up to 25% of budget (50KB)
});
Legacy Number Configuration
// Still supported for backwards compatibility
const cache = new MicroCache('namespace', 100 * 1024);
// Equivalent to:
// { budget: 100 * 1024, maxEntrySize: 8 * 1024 }
๐จ Troubleshooting
Issue: Cache Persists After Nuclear Reset
Symptoms: Data still visible after nuclear reset
Solution:
// Ensure using GgStorage.nuclearCacheReset()
GgStorage.nuclearCacheReset();
// Verify all cache cleared
const remaining = MicroCache.getAllNamespaceKeys();
console.log('Remaining keys:', remaining); // Should be []
Issue: Cross-Tenant Data Leakage
Symptoms: Tenant A sees Tenant B's data
Solution:
// Always use unique namespaces
const tenantACache = new MicroCache(`tenant-${tenantA.id}`);
const tenantBCache = new MicroCache(`tenant-${tenantB.id}`);
// Never share instances
// โ BAD: const cache = new MicroCache('shared');
Issue: localStorage Quota Exceeded
Symptoms: QuotaExceededError
Solution:
// Reduce budgets
const cache = new MicroCache('namespace', {
budget: 50 * 1024, // Reduce from 100KB to 50KB
});
// Or enable aggressive eviction
cache.pruneExpired(); // Remove expired entries first
๐ Performance Characteristics
| Operation | Time | Notes |
|---|---|---|
get() |
< 1ms | localStorage read + JSON.parse |
set() |
< 2ms | JSON.stringify + localStorage write |
clear() |
< 5ms | Remove all namespace entries |
clearAllNamespaces() |
< 50ms | Global scan + removal |
pruneExpired() |
< 10ms | Scan + remove expired |
๐ Advanced Topics
Custom Eviction Strategy
The micro-cache uses LFU-LRU hybrid eviction:
Score = (accessCount * 0.3) + (recency * 0.7)
- 30% weight on frequency (how often accessed)
- 70% weight on recency (how recently accessed)
- Lower score = evicted first
TTL Management
// Set with TTL
cache.set('session-token', token, 60 * 60 * 1000); // 1 hour TTL
// Auto-removed after 1 hour
// Or on next pruneExpired() call
cache.pruneExpired();
๐ Related Documentation
- Offline-First Sync Engine - Background synchronization
- Offline-First Architecture - Complete system architecture
- Flash Persistence - Persistent signals
- Multi-Tenant Guide - Multi-tenant patterns
Built: November 3, 2025
Status: โ
Production Ready
Performance: Sub-1ms cache access
Impact: Critical for offline-first architecture
The foundation for lightning-fast data access in the platform builder. โก