npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bridge-cache

v0.1.1

Published

In-memory cache bridge for frequently requested Node.js data with automatic invalidation

Downloads

190

Readme

bridge-cache

A production-ready in-memory cache for Node.js applications.

It is designed as a bridge for frequently requested data such as API responses, DB query results, computed objects, and JSON data.

Why this package

  • Fast in-memory reads for hot data.
  • Automatic invalidation by default (safe behavior if you forget options).
  • Per-key invalidation options (ttlMs, absoluteExpiryAt, tags).
  • Capacity controls with eviction strategies (lru / fifo).
  • Stampede protection with getOrSet (single-flight loading).
  • Small API surface, easy to adopt.

Install

npm install bridge-cache

Quick start

const { createCache } = require("bridge-cache");

const cache = createCache();

cache.set("app:config", { featureA: true });
const config = cache.get("app:config");

console.log(config);

If you call set without options, default TTL invalidation applies automatically (default: 5 minutes).

Core concepts

  • set stores value with optional invalidation options.
  • get returns value on hit, undefined on miss/expired.
  • getOrSet fetches once for concurrent callers and stores result.
  • invalidateTag invalidates grouped keys.
  • invalidateWhere invalidates keys by custom predicate.
  • stats gives counters and hit rate.

API

createCache(options?)

Creates an in-memory cache instance.

const cache = createCache({
  defaultTtlMs: 5 * 60 * 1000,
  maxEntries: 10_000,
  maxSizeBytes: 64 * 1024 * 1024,
  sweepIntervalMs: 60_000,
  evictionPolicy: "lru",
  cloneOnGet: false,
  cloneOnSet: false,
  onEvent: (event) => {
    // Optional telemetry hook
    console.log(event.type, event.key);
  },
});

Options:

  • defaultTtlMs (default 300000): fallback expiry when set has no ttl options.
  • maxEntries (default 10000): maximum number of entries.
  • maxSizeBytes (default 67108864): maximum total cache size.
  • sweepIntervalMs (default 60000): periodic cleanup interval for expired entries.
  • evictionPolicy (default "lru"): "lru" or "fifo".
  • cloneOnGet / cloneOnSet: optional defensive cloning.
  • onEvent: callback for cache events (hit, miss, set, delete, expired, evicted, clear).

set(key, value, options?)

Stores a value.

cache.set("user:1", { id: 1, name: "Ana" }, { ttlMs: 60_000, tags: ["user"] });

Set options:

  • ttlMs: relative expiry in milliseconds.
  • absoluteExpiryAt: absolute Unix epoch timestamp in milliseconds.
  • tags: label list for grouped invalidation.

Behavior:

  • If absoluteExpiryAt is provided, it is used.
  • Else if ttlMs is provided, it is used.
  • Else defaultTtlMs is applied automatically.

get(key) and has(key)

const value = cache.get("user:1");
if (cache.has("user:1")) {
  // key exists and is not expired
}

Expired entries are invalidated automatically on access.

delete(key) and clear()

cache.delete("user:1");
cache.clear();

invalidateTag(tag)

cache.set("user:1", { id: 1 }, { tags: ["tenant:a", "user"] });
cache.set("user:2", { id: 2 }, { tags: ["tenant:a", "user"] });

const removed = cache.invalidateTag("tenant:a");
console.log(removed); // 2

invalidateWhere(predicate)

cache.invalidateWhere((entry, key) => key.startsWith("product:") && entry.accessCount === 0);

getOrSet(key, loader, options?)

Prevents duplicate concurrent loads for the same key.

const profile = await cache.getOrSet(
  "user:1:profile",
  async () => {
    // Only one caller runs this loader concurrently per key
    return fetchUserProfileFromDB(1);
  },
  { ttlMs: 120_000, tags: ["user", "profile"] }
);

stats()

console.log(cache.stats());
// {
//   hits, misses, sets, deletes,
//   evictions, expirations,
//   count, sizeBytes, hitRate
// }

stop()

Stops the internal sweeper interval (recommended in tests/short-lived workers).

cache.stop();

End-to-end usage examples

1. Cache DB results by id

const { createCache } = require("bridge-cache");

const cache = createCache({ defaultTtlMs: 30_000 });

async function getUser(id) {
  return cache.getOrSet(`user:${id}`, async () => {
    return db.users.findById(id);
  }, { tags: ["user"] });
}

2. Cache external API response

const weatherCache = createCache({ defaultTtlMs: 60_000 });

async function getWeather(city) {
  return weatherCache.getOrSet(`weather:${city}`, async () => {
    const res = await fetch(`https://api.example.com/weather?city=${city}`);
    return res.json();
  }, { tags: ["weather"] });
}

3. Invalidate related data after write

async function updateUser(userId, payload) {
  await db.users.update(userId, payload);
  cache.invalidateTag("user");
}

Complete Example

Create a file named example.js:

const { createCache } = require('bridge-cache');

async function run() {
  // 1. Initialize the cache 
  const cache = createCache({
    defaultTtlMs: 60000, // 1 minute
    maxEntries: 100,
    evictionPolicy: 'lru'
  });

  // 2. Set some generic data
  cache.set('user:123', { name: "Alice", active: true }, { tags: ['users'] });
  console.log("User:", cache.get('user:123'));

  // 3. getOrSet pattern (only executes loader if cache misses)
  const apiData = await cache.getOrSet('weather:nyc', async () => {
    console.log("Simulating slow API call...");
    await new Promise(resolve => setTimeout(resolve, 500)); // Sleep
    return { temp: 72, condition: "Sunny" };
  }, { ttlMs: 15000 });

  console.log("Weather:", apiData);

  // 4. Invalidation
  const removed = cache.invalidateTag('users');
  console.log(`Removed ${removed} entries.`);
  console.log("User after invalidation:", cache.get('user:123')); // undefined

  // 5. Cleanup memory interval at process exit
  cache.stop();
}

run();

Data support

Supported well in v1:

  • JSON-friendly objects
  • arrays
  • strings
  • numbers
  • booleans
  • null

Notes:

  • undefined values are rejected.
  • Circular references are rejected (size estimation requires serialization).

Default invalidation strategy

If no invalidation options are passed in set, the package still invalidates automatically:

  • Applies defaultTtlMs (5 minutes by default).
  • Periodic sweep removes expired entries.
  • Capacity checks evict entries when limits are exceeded.

This prevents accidental never-expiring cache entries.

Production recommendations

  • Start with:
    • defaultTtlMs: 300000
    • maxEntries: 10000
    • maxSizeBytes: 64 * 1024 * 1024
    • evictionPolicy: "lru"
  • Add tags for domain-based invalidation (user, catalog, tenant:x).
  • Export stats() to logs/metrics for capacity tuning.
  • Use getOrSet for expensive loaders to prevent traffic spikes.

Development

npm install
npm run build
npm test

Roadmap ideas

  • Redis adapter.
  • Stale-while-revalidate mode.
  • Namespace support.
  • Multi-process invalidation hooks.

Detailed design document

Implementation deep dive is available at:

CACHE_PACKAGE_IMPLEMENTATION_GUIDE.md