Skip to main content

Caching Architecture

Learn how LiveI18n's intelligent caching system works and how to configure it for optimal performance.

Overview

LiveI18n uses a sophisticated multi-layer caching approach:

  1. Client-side Hybrid Cache - Fast memory + persistent storage (default: 500 entries, 1-hour TTL)
  2. Server-side Cache - Redis cache on our API servers (24-hour TTL)
  3. Platform-Optimized Storage - localStorage (web) or AsyncStorage (React Native)

Client-Side Caching

Hybrid Cache Architecture

LiveI18n uses a hybrid cache system combining fast in-memory storage with persistent storage:

Memory Layer (LRU Cache)

  • Lightning-fast access (< 1ms)
  • 500 entries by default (customizable)
  • 1-hour TTL by default (customizable)
  • Survives page navigation

Persistent Layer (localStorage/AsyncStorage)

  • Survives browser refresh and app restarts
  • Same size and TTL as memory layer
  • Platform-optimized storage
  • Automatic synchronization with memory cache
// First visit - API call, cached in both layers
<LiveText>Welcome to our app!</LiveText> // ~200ms

// Same session - memory cache hit
<LiveText>Welcome to our app!</LiveText> // < 1ms

// After refresh - persistent cache hit, loaded to memory
<LiveText>Welcome to our app!</LiveText> // ~5ms

Cache Configuration

Configure cache behavior during SDK initialization:

// Default: Persistent cache with 500 entries, 1-hour TTL (both customizable)
<LiveI18nProvider config={{
apiKey: 'your-api-key',
customerId: 'your-customer-id'
}}>
<YourApp />
</LiveI18nProvider>

// Custom cache size and TTL
<LiveI18nProvider config={{
apiKey: 'your-api-key',
customerId: 'your-customer-id',
cache: {
entrySize: 1000, // Number of cache entries
ttlHours: 24, // Cache TTL in hours
persistent: true, // Use persistent storage (default)
preload: true // Preload cache on startup (default: false)
}
}}>
<YourApp />
</LiveI18nProvider>

// Memory-only cache (no persistence)
<LiveI18nProvider config={{
apiKey: 'your-api-key',
customerId: 'your-customer-id',
cache: {
persistent: false, // Disable persistent storage
entrySize: 500, // Memory cache only
ttlHours: 1
}
}}>
<YourApp />
</LiveI18nProvider>

Cache Key Generation

LiveI18n uses canonical cache keys to maximize cache efficiency:

// These all generate the same cache key (normalized):
<LiveText context="greeting">Hello</LiveText>
<LiveText context="Greeting">Hello</LiveText>
<LiveText context="greeting ">Hello</LiveText> // Extra space ignored

// These generate different cache keys:
<LiveText context="greeting">Hello</LiveText>
<LiveText context="farewell">Hello</LiveText>
<LiveText tone="friendly" context="greeting">Hello</LiveText>

Server-Side Caching

Redis Cache

Our API servers use Redis for distributed caching:

  • 24-hour TTL for stable translations
  • Automatic cache key generation using the same algorithm as client
  • Per-customer isolation for security and performance

Cache Warming

Pre-populate cache for better performance:

// Warm cache with common translations
const commonTexts = [
'Welcome',
'Sign In',
'Sign Up',
'Contact Us',
'About',
'Home'
];

// These will be cached for future use
commonTexts.forEach(text => {
// Render off-screen to trigger caching
const element = document.createElement('div');
element.style.display = 'none';
ReactDOM.render(<LiveText>{text}</LiveText>, element);
});

Optimization Strategies

1. Consistent Text Usage

// ✅ Good - creates single cache entry
const BUTTON_TEXT = 'Add to Cart';
<LiveText context="shopping">{BUTTON_TEXT}</LiveText>
<LiveText context="shopping">{BUTTON_TEXT}</LiveText>

// ❌ Avoid - creates multiple cache entries
<LiveText context="shopping">Add to Cart</LiveText>
<LiveText context="shopping">Add To Cart</LiveText> // Different case

2. Stable Context and Tone

// ✅ Good - consistent parameters
const CONTEXT = 'product page';
const TONE = 'marketing';

<LiveText context={CONTEXT} tone={TONE}>Special Offer!</LiveText>
<LiveText context={CONTEXT} tone={TONE}>Limited Time!</LiveText>

// ❌ Avoid - dynamic parameters that change frequently
<LiveText context={`product-${product.id}`}>Add to Cart</LiveText>

3. Batch Similar Translations

// ✅ Good - similar context allows batch processing
const navigationItems = ['Home', 'About', 'Products', 'Contact'];

{navigationItems.map(item => (
<LiveText key={item} context="navigation">
{item}
</LiveText>
))}

4. Avoid Cache Pollution

// ❌ Avoid - creates too many cache entries
<LiveText>User {userId} logged in</LiveText> // Different for each user

// ✅ Better - separate static and dynamic content
<LiveText context="status">User logged in:</LiveText> {username}

Advanced Caching Techniques

Pre-loading Translations

Pre-load translations for better UX:

import { useMemo, useEffect } from 'react';

function PreloadTranslations({ texts }) {
const cachedTexts = useMemo(() => {
// Pre-render texts to trigger caching
return texts.map(text => (
<div key={text} style={{ display: 'none' }}>
<LiveText>{text}</LiveText>
</div>
));
}, [texts]);

return <div>{cachedTexts}</div>;
}

// Usage - pre-load common UI text
function App() {
return (
<div>
<PreloadTranslations texts={[
'Loading...',
'Error occurred',
'Success!',
'Please wait'
]} />
{/* Rest of your app */}
</div>
);
}

Route-Based Cache Warming

Pre-load translations for the next likely page:

import { useEffect } from 'react';
import { useRouter } from 'next/router';

function useRouteBasedCaching() {
const router = useRouter();

useEffect(() => {
const preloadTexts = (route) => {
const routeTexts = {
'/products': ['Add to Cart', 'Product Details', 'Price'],
'/checkout': ['Checkout', 'Payment', 'Shipping'],
'/profile': ['Profile', 'Settings', 'Account']
};

return routeTexts[route] || [];
};

// Pre-cache likely next page content
const currentRoute = router.pathname;
const likelyNextRoutes = getLikelyNextRoutes(currentRoute);

likelyNextRoutes.forEach(route => {
const texts = preloadTexts(route);
texts.forEach(text => {
// Trigger caching without rendering
cachePrefetch(text);
});
});
}, [router.pathname]);
}

Component-Level Caching

Implement component-level caching for complex translations:

import { memo, useMemo } from 'react';

const CachedTranslation = memo(function CachedTranslation({
text,
context,
tone,
dependencies = []
}) {
const memoizedTranslation = useMemo(() => (
<LiveText context={context} tone={tone}>
{text}
</LiveText>
), [text, context, tone, ...dependencies]);

return memoizedTranslation;
});

// Usage - only re-translates when dependencies change
function ProductCard({ product, userLanguage }) {
return (
<div>
<CachedTranslation
text={product.description}
context="product-description"
tone="marketing"
dependencies={[userLanguage]} // Re-translate when language changes
/>
</div>
);
}

Cache Management

The LiveI18n SDK provides built-in cache management with automatic cleanup and optimization.

Performance Metrics

Expected Performance

With proper caching:

  • Cache Hits: 1ms response time
  • Cache Misses: 100-500ms response time
  • Memory Usage: ~10MB for 1000 cached translations
  • Hit Ratio: 85-95% for typical applications

Measuring Performance

// Performance monitoring
const measureTranslationPerformance = async (text, options) => {
const start = performance.now();

const result = await translate(text, options);

const end = performance.now();
const duration = end - start;

console.log(`Translation took ${duration}ms`, {
text,
cached: duration < 10, // Likely cached if very fast
performance: duration < 100 ? 'excellent' : 'good'
});

return result;
};

Best Practices Summary

Do's ✅

  • Use consistent text, context, and tone
  • Pre-load common translations
  • Monitor cache hit rates
  • Implement route-based pre-caching
  • Use stable cache keys

Don'ts ❌

  • Don't include dynamic data in translatable text
  • Don't change context/tone frequently for the same text
  • Don't disable caching unless necessary
  • Don't translate technical terms or proper nouns
  • Don't ignore cache performance metrics

Troubleshooting

Low Cache Hit Rates

Symptoms: Frequent API calls, slow performance Solutions:

  • Check for dynamic content in translations
  • Verify consistent context/tone usage
  • Monitor cache key generation

High Memory Usage

Symptoms: Browser slowdown, memory warnings Solutions:

  • Reduce cache size limit
  • Implement more aggressive TTL
  • Clear cache periodically

Stale Translations

Symptoms: Old translations showing after content updates Solutions:

  • Clear client cache after deployments
  • Implement cache versioning
  • Use shorter TTL for frequently changing content

Testing Cache Behavior

Development Testing

// Test cache behavior in development
const testCachePerformance = () => {
const texts = ['Hello', 'Welcome', 'Goodbye'];

texts.forEach(async (text, index) => {
console.time(`Translation ${index + 1}`);

// First call - should be slow (cache miss)
await translate(text);
console.timeEnd(`Translation ${index + 1} - First`);

console.time(`Translation ${index + 1} - Second`);

// Second call - should be fast (cache hit)
await translate(text);
console.timeEnd(`Translation ${index + 1} - Second`);
});
};

Production Monitoring

// Monitor cache performance in production
const trackCacheMetrics = () => {
const metrics = {
hits: 0,
misses: 0,
totalRequests: 0
};

// Override translate function to track metrics
const originalTranslate = window.LiveI18n.translate;

window.LiveI18n.translate = async (...args) => {
const start = performance.now();
const result = await originalTranslate.apply(this, args);
const duration = performance.now() - start;

metrics.totalRequests++;

if (duration < 10) {
metrics.hits++;
} else {
metrics.misses++;
}

// Send metrics to analytics
if (metrics.totalRequests % 100 === 0) {
analytics.track('cache_performance', {
hitRate: (metrics.hits / metrics.totalRequests) * 100,
avgDuration: duration
});
}

return result;
};
};

Next Steps

Need Help?

Questions about caching strategies?

  • Check our troubleshooting guide
  • Join our Discord for performance discussions
  • Contact support for enterprise caching solutions