Turning Moleculer Actions into Lightning‑Fast Endpoints with the Built‑In Memory Cacher
Learn how to enable Moleculer’s Memory cacher for service actions, see a step‑by‑step example, understand key trade‑offs, and decide when a distributed cacher is needed.
26 Jun 2026, 03:43 UTC

Why Cache an Action?
In a microservice architecture, many actions perform the same read‑only work over and over: fetching a user profile, calculating a discount, or formatting a report. If the underlying data doesn’t change frequently, caching the result can cut latency by 90 % and reduce load on databases or third‑party APIs. Moleculer’s cacher abstraction lets you do this without touching the action logic.
Getting Started: The Memory Cacher
The Memory cacher is the simplest out‑of‑the‑box option. It keeps all cache entries in a Node.js Map, so lookups are O(1). It is ideal for development, low‑traffic services, or when you run a single broker instance.
Step 1 – Install Moleculer
# npm install moleculer
Step 2 – Create a Service with Caching Enabled
Below is a minimal service that returns the current timestamp. The cache: true flag tells Moleculer to store the result in the configured cacher.
// services/time.service.js
module.exports = {
name: "time",
actions: {
now: {
cache: true, // enable caching for this action
async handler() {
return { ts: Date.now() };
}
}
}
};
Step 3 – Configure the Broker with the Memory Cacher
In the broker configuration you can simply set cacher: true to use the default Memory cacher. Optionally, set a global TTL that applies to all cached actions.
// broker.js
const { ServiceBroker } = require("moleculer");
const broker = new ServiceBroker({
nodeID: "node-1",
cacher: true, // use Memory cacher
cacherOptions: {
ttl: 6000 // 6 seconds default for all actions
}
});
broker.loadService("./services/time.service.js");
broker.start();
Testing the Cache in Action
Run the broker and call the action twice. The second call should return the same timestamp and log a cache hit. You can observe the log by enabling the debug level:
node broker.js --log-level debug
Expected log snippet:
[debug] Cache hit: time.now
After waiting longer than the TTL (e.g., 7 seconds), call the action again – a new timestamp should appear, indicating the entry expired.
Fine‑Tuning Cache Keys
By default, Moleculer hashes the entire params object to generate a cache key. If you have actions with many parameters but only a subset influences the result, you can reduce collision risk by specifying keys:
now: {
cache: { ttl: 12000, keys: ["userId"] }
}
Now only the userId field will be part of the cache key, ignoring extraneous data such as pagination tokens.
When the Memory Cacher Falls Short
- Single‑Process Limitation: Each Node.js process has its own cache. In a horizontally scaled environment, two broker instances will not share cached data, leading to inconsistent responses.
- Stale Data: The default TTL is a best‑effort approach. If your data source changes immediately after a cache is set, consumers may receive stale results until the TTL expires. Manual invalidation via
this.broker.cacher.flush()or a cache‑clear action is required. - Memory Footprint: All cached entries live in RAM. For services that cache large payloads or have a high cache hit rate, memory consumption can grow quickly.
Upgrading to a Distributed Cacher (Redis)
When you need cross‑instance cache sharing or larger storage, swap the Memory cacher for Redis. Install the Moleculer‑Redis adapter and configure the broker accordingly.
# npm install moleculer-redis redis
// broker.js – Redis cacher
const { ServiceBroker } = require("moleculer");
const { RedisCacher } = require("moleculer-redis");
const redis = require("redis");
const broker = new ServiceBroker({
nodeID: "node-1",
cacher: new RedisCacher({
redis: redis.createClient({ url: "redis://localhost:6379" })
})
});
With Redis, cache hits are shared across all broker instances, solving the consistency issue. However, you now depend on an external service and must handle connection errors and persistence settings.
Practical Checklist
- Verify the broker log for
Cache hitmessages after the first call. - Set a short TTL (e.g., 2 s) and confirm a new value after expiration.
- In a multi‑instance test, ensure the same key returns the cached value across nodes.
- Watch memory usage (e.g.,
toporprocess.memoryUsage()) when using Memory cacher with large payloads.
Actionable Takeaway
Start with the Memory cacher for quick performance gains in single‑node deployments. If you scale horizontally or need tighter consistency, migrate to Redis or another distributed cacher. Always tailor cache: { ttl, keys } to the action’s semantics to avoid unnecessary cache collisions or stale data. With these steps, Moleculer’s caching can turn a slow database read into a near‑instant response without rewriting your business logic.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.