Cut Database Load with Moleculer’s Built‑In Cache Service – A Practical Guide
Use Moleculer’s Cache Service to cut database load. Enable Redis caching, set TTLs, invalidate on updates, and monitor hits/misses. A practical guide with code, trade‑offs, and an actionable checklist.
12 Sept 2026, 14:01 UTC

Why Cache the Results of a Moleculer Action?
When a service repeatedly returns the same data – for example, a user profile or a product catalog – every call forces a round‑trip to the database. This adds latency, consumes CPU, and can spike the load on a shared DB. Moleculer ships a Cache Service that can be turned on per‑service or globally, turning a hot‑path into a fast memory lookup.
Key Features at a Glance
- Automatic cache key generation from action parameters.
- TTL (time‑to‑live) per key, with optional zero to disable caching.
- Built‑in adapters:
Memory(in‑process),Redis(distributed), or custom stores. - Programmatic invalidation:
broker.cache.remove(key)orbroker.cache.clear(). - Metrics:
cache.hits,cache.missesexposed viabroker.metrics. - Integration with Moleculer events for automatic invalidation on data changes.
Setting Up a Redis‑Backed Cache
Below is a minimal example that demonstrates how to wire the cache into a Moleculer broker and a single service. The example assumes you have a running Redis instance on localhost:6379.
// broker.js
const { ServiceBroker } = require("moleculer");
const { CacheService } = require("moleculer-cache");
const broker = new ServiceBroker({
nodeID: "cache-demo",
// Enable the cache globally
cache: {
enabled: true,
adapter: {
type: "redis",
options: {
host: "localhost",
port: 6379
}
}
}
});
broker.createService({
name: "user",
actions: {
// The cache is enabled per action via the `cache` option
getProfile: {
cache: { ttl: 60 }, // cache for 60 seconds
async handler(ctx) {
// Simulate a DB call
const user = await db.getUserById(ctx.params.id);
return user;
}
}
}
});
broker.start();
Run the broker with node broker.js. The first call to user.getProfile will hit the database. Subsequent calls within 60 seconds will return the cached result, and the DB query count will stay unchanged.
Verifying Cache Hits
After the broker is running, you can observe the cache metrics:
curl http://localhost:3000/metrics
Look for cache.hits and cache.misses. A hit count greater than zero indicates that the cache is being used. You can also inspect Redis directly:
redis-cli keys "moleculer:cache:*"
redis-cli ttl "moleculer:cache:user.getProfile:123"
The TTL value will show the remaining time before the key expires.
Manual Invalidation – When the Data Changes
Cache staleness is the most common pitfall. Whenever the underlying data changes, you should invalidate the related cache entry:
// In a service that updates user data
async updateProfile(ctx) {
const updated = await db.updateUser(ctx.params.id, ctx.params.data);
// Invalidate cache for the updated user
broker.cache.remove("user.getProfile:" + ctx.params.id);
return updated;
}
Alternatively, if many keys need clearing, use broker.cache.clear(). This is useful after bulk imports.
Trade‑Offs and Limitations
- Memory vs. Persistence: The
Memoryadapter is the fastest but loses data on broker restart. Redis keeps data across restarts but adds network latency. - Staleness Risk: A long TTL can serve out-of‑date data. Zero TTL disables caching, which is a safe fallback.
- Cache Size: Large objects can exhaust node memory or Redis memory limits. Monitor
cache.hitsandcache.missesto detect spikes. - Over‑caching: If the DB is already fast or the dataset is small, caching may add unnecessary complexity.
Actionable Checklist
- Enable
cache.enabledin the broker config and choose an adapter that matches your scaling needs. - Mark specific actions with
cache: { ttl: X }and test that the first call hits the DB while subsequent calls use the cache. - Add manual invalidation in all write paths that modify the cached data.
- Expose
cache.hitsandcache.missesin your monitoring stack. - Periodically review TTL values and cache sizes; adjust if you see a high miss rate or memory warnings.
By following these steps, you can reduce database load, lower latency for read‑heavy services, and keep your application responsive without sacrificing data correctness.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.