How to Optimize Cache Performance and Tune Cache Metrics in MiniSearch
To optimize cache performance in MiniSearch, configure the TTL and entry limits via updateCacheConfig(), monitor hit rates through the built-in cacheMetrics system, and adjust pruning intervals to balance storage efficiency with query speed.
MiniSearch implements a lightweight, in-browser IndexedDB cache that stores text and image query results for fast retrieval. The cache is deliberately configurable, allowing you to balance result freshness, memory usage, and visibility into cache efficiency. By tuning specific parameters in client/modules/search.ts and monitoring the exposed metrics, you can significantly improve the hit rate while controlling storage overhead.
Core Cache Configuration Strategies
Adjusting Time-to-Live (TTL) for Freshness
The TTL (time-to-live) parameter defines how long a cached result remains valid before eviction. In client/modules/search.ts (lines 31-33), the default TTL can be overridden at runtime to match your content's update frequency.
Shorten the TTL for rapidly changing data (e.g., news feeds) or extend it for static reference material:
import { updateCacheConfig } from "./client/modules/search";
// Set TTL to 5 minutes for fresher results
updateCacheConfig({ ttl: 5 * 60 * 1000 });
// Or extend to 24 hours for stable content
updateCacheConfig({ ttl: 24 * 60 * 60 * 1000 });
Limiting Storage with maxEntries
To prevent unbounded growth in IndexedDB, MiniSearch enforces a maxEntries cap (lines 34-35). Once the limit is reached, the cache prunes the oldest entries automatically. Increase this value for high-query-volume deployments or reduce it for memory-constrained environments:
// Increase capacity to 200 distinct queries
updateCacheConfig({ maxEntries: 200 });
// Reduce footprint on low-memory devices
updateCacheConfig({ maxEntries: 50 });
Enabling and Disabling the Cache at Runtime
The enabled flag (line 36) provides an immediate kill switch for caching without requiring a code redeployment. This is useful for debugging or temporary troubleshooting:
// Temporarily bypass the cache
updateCacheConfig({ enabled: false });
// Re-enable when ready
updateCacheConfig({ enabled: true });
Advanced Tuning and Maintenance
Throttling Cleanup with PRUNE_INTERVAL
MiniSearch spreads the cost of cache maintenance by running a cleanup pass only after every PRUNE_INTERVAL writes (line 17). This constant is defined internally and governs how aggressively the cache reclaims expired entries.
A lower interval triggers more frequent pruning, reducing storage pressure but increasing write overhead. While this constant is not yet exposed in the public API, you can modify it directly in client/modules/search.ts if your deployment requires different cleanup characteristics.
Manual Cache Clearing
For user-initiated resets or administrative functions, the clearCache() helper removes all IndexedDB entries immediately:
import { clearCache } from "./client/modules/search";
async function handleReset() {
try {
await clearCache();
console.log("Search cache cleared successfully");
} catch (error) {
console.error("Failed to clear cache:", error);
}
}
Monitoring and Metrics
Tracking Hit Rates with cacheMetrics
The cacheMetrics object (lines 42-88) maintains counters for text-hits, text-misses, image-hits, image-misses, and total operations. It automatically computes hit rates and logs summaries every METRICS_LOG_INTERVAL operations to prevent counter overflow.
These metrics allow you to quantify the effectiveness of your TTL and maxEntries settings.
Accessing Metrics Programmatically
Every search operation returns an object containing textHitRate, imageHitRate, and raw hit/miss counts (lines 575-581). You can capture these to display real-time statistics in your UI or log them for analysis:
const results = await performSearch("query string");
console.log(`Text cache hit rate: ${(results.textHitRate * 100).toFixed(1)}%`);
console.log(`Image cache hit rate: ${(results.imageHitRate * 100).toFixed(1)}%`);
console.log(`Total cache operations: ${results.totalOperations}`);
Resetting Metrics for Baseline Analysis
To establish a fresh performance baseline after configuration changes, call resetMetrics() on the internal cacheMetrics instance (lines 81-86). This zeros all counters and hit-rate calculations:
// Access the internal metrics instance (within the search module context)
cacheMetrics.resetMetrics();
HTTP Cache Headers for Static Assets
Configuring Cache-Control in Development and Production
While the IndexedDB cache handles query results, MiniSearch also optimizes static asset delivery through the Vite preview server. The cacheServerHook.ts file (lines 9-22) injects Cache-Control headers based on the environment:
- Development:
public, max-age=86400, must-revalidate - Production:
public, max-age=31536000, immutable - Disabled:
no-cache
Register this hook in your vite.config.ts to enable browser-level caching for JavaScript bundles and icons:
import { cacheServerHook } from "./server/cacheServerHook";
import { defineConfig } from "vite";
export default defineConfig({
preview: {
configurePreviewServer: cacheServerHook,
},
});
Summary
- Tune freshness and capacity by adjusting
ttlandmaxEntriesviaupdateCacheConfig()inclient/modules/search.tsto match your data volatility and storage constraints. - Control runtime behavior using the
enabledflag to toggle caching without redeployment, and modifyPRUNE_INTERVALto balance cleanup frequency with write performance. - Monitor effectiveness through the
cacheMetricssystem, which exposestextHitRateandimageHitRateon every search operation and logs aggregated statistics automatically. - Clear state manually using
clearCache()for administrative resets or user-requested purges. - Optimize asset delivery by enabling the
cacheServerHook.tsmiddleware to set long-term immutable headers for static files in production.
Frequently Asked Questions
How do I calculate the optimal TTL for my MiniSearch deployment?
Choose a TTL that matches your content update frequency. For real-time data like news or stock prices, set ttl to 300000 (5 minutes) or lower using updateCacheConfig({ ttl: 5 * 60 * 1000 }). For static documentation or archived content, use 86400000 (24 hours) or longer to maximize cache hits and reduce API calls.
What happens when the cache reaches the maxEntries limit?
When the number of stored entries exceeds maxEntries, MiniSearch automatically prunes the oldest records to maintain the cap. This LRU-style eviction occurs during write operations and is throttled by the PRUNE_INTERVAL constant to prevent performance spikes.
Can I disable caching only for specific query types?
The current implementation in client/modules/search.ts provides a global enabled flag that affects all cached operations. To disable caching for specific query types, you would need to wrap the search call with a conditional that checks the query category before invoking the cache-enabled search function, or modify the internal cacheResult method to accept query-type parameters.
Where can I view the cache hit rate in real-time?
The performSearch() function returns a statistics object containing textHitRate and imageHitRate as floating-point values between 0 and 1. Poll this function or intercept its return value in your application state manager to display live metrics. The internal cacheMetrics object also logs a summary to the console every METRICS_LOG_INTERVAL operations if you need historical trend analysis.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →