← Back to archive

Repo of the Day

Julien-R44/bentocache

Published: Dec 28, 2024

Open repository ↗

Bentocache is a robust multi-tier caching solution for Node.js applications

Summary

Bentocache is a TypeScript caching library for Node.js that combines a fast in-memory L1 layer with a distributed L2 store such as Redis, keeping local caches synchronized across instances through a pub/sub bus. The README positions it as a full-featured caching solution rather than a thin adapter like keyv, cache-manager, or unstorage, with production-oriented behaviors (grace periods, stampede protection, tagging, OpenTelemetry) built in.

What it is useful for

  • Reducing read latency for hot data by serving most requests from in-process LRU memory while still sharing state across nodes through Redis or another distributed backend.
  • Surviving backend outages: the documented grace-period and timeout features let the cache return stale data when the source-of-truth or a slow factory is unhealthy, while a recompute runs in the background.
  • Simplifying bulk invalidation through namespaces (clear a whole group at once) or tags (associate entries with ['tag-1', 'tag-2'] and call deleteByTag).
  • Standardizing on a single caching API across heterogeneous storage, since the driver list in the README covers Redis, Upstash, MySQL, PostgreSQL, SQLite, DynamoDB, Filesystem, Vercel KV, and an in-memory LRU driver, with an extension point for custom drivers.
  • Adding observability without extra wiring: events like cache:hit and cache:miss for metrics, a Pino logger option, and an official @bentocache/otel package for OpenTelemetry-compatible tracers (Jaeger, Zipkin, Datadog, New Relog, etc.).

How engineers can use it

The README does not include a full install/quickstart, so the initial setup (choosing a driver, wiring a bus, configuring timeouts) must be taken from the linked documentation at bentocache.dev rather than copied from this repository.

From the documented usage snippets, a typical flow is:

  1. Create a BentoCache instance with one or more drivers and, for multi-instance deployments, a bus such as Redis or RabbitMQ so local L1 caches stay in sync.
  2. Read or compute values with bento.getOrSet({ key, factory, ttl }). TTLs accept human-readable strings like '2.5h' (via lukeed/ms) or plain millisecond numbers.
  3. Group entries by namespace:
    const users = bento.namespace('users')
    users.set({ key: '32', value: { name: 'foo' } })
    users.clear()
    
  4. Tag writes for later targeted invalidation:
    await bento.getOrSet({ key: 'foo', factory: getFromDb(), tags: ['tag-1', 'tag-2'] })
    await bento.deleteByTag({ tags: ['tag-1'] })
    
  5. Subscribe to events (bento.on('cache:hit', ...)) for metrics, and add @bentocache/otel if your stack already runs an OpenTelemetry pipeline.

Documented limitation: the README references performance comparisons and a "2,000x to 5,000x faster" claim tied to its own benchmark image; treat those numbers as project-reported rather than independently verified.