New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

express-memorize

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-memorize

In-memory cache middleware for Express.js. Caches GET responses with optional TTL — zero dependencies, fully typed.

latest
Source
npmnpm
Version
1.4.0
Version published
Maintainers
1
Created
Source

express-memorize

npm version npm downloads CI license TypeScript

In-memory cache middleware for Express.js.
Caches GET responses with optional TTL — zero dependencies, fully typed.

Features

  • Caches GET responses automatically when status code is 2xx
  • Per-route TTL override
  • Event hooks: set, delete, expire
  • Cache inspection and invalidation API
  • Hit counter per cache entry
  • X-Cache: HIT | MISS | BYPASS response header
  • Zero runtime dependencies
  • Full TypeScript support

Installation

npm install express-memorize

Quick Start

import express from 'express';
import { memorize } from 'express-memorize';

const app = express();
const cache = memorize({ ttl: 30_000 }); // 30 seconds global TTL

app.get('/users', cache(), async (req, res) => {
  const users = await db.getUsers();
  res.json({ data: users });
});

app.listen(3000);

The first request computes the response normally. Every subsequent GET /users is served from memory until the TTL expires.

Usage

Global middleware

Apply the cache to the entire application with app.use(). Every GET route is cached automatically — non-GET requests are bypassed without any extra configuration.

const cache = memorize({ ttl: 60_000 });

app.use(cache()); // applies to all GET routes

app.get('/users',   (req, res) => { res.json({ data: users }) });
app.get('/products', (req, res) => { res.json({ data: products }) });
// POST, PUT, PATCH, DELETE routes are unaffected

Per-route cache

const cache = memorize({ ttl: 60_000 });

app.get('/products', cache(), (req, res) => {
  res.json({ data: products });
});

Per-route TTL override

const cache = memorize({ ttl: 60_000 }); // global: 60s

app.get('/users',    cache(),               handler); // 60s
app.get('/products', cache({ ttl: 10_000 }), handler); // override: 10s
app.get('/config',   cache({ ttl: 0 }),      handler); // no expiry

Cache invalidation

const cache = memorize({ ttl: 30_000 });

app.get('/users', cache(), (req, res) => {
  res.json({ data: users });
});

app.post('/users', (req, res) => {
  users.push(req.body);
  cache.delete('/users'); // invalidate after mutation
  res.status(201).json({ data: req.body });
});

Pattern-based invalidation

Use cache.deleteMatching(pattern) to remove all cache entries whose keys match a glob pattern. This is useful when you don't know the exact key — for example, when a URL may have different query strings.

// Cached keys: /api/users/abc123, /api/users/abc123?lang=es, /api/users/abc123?page=1
app.put('/users/:id', (req, res) => {
  users.update(req.params.id, req.body);

  // Remove all cached variants of this user, regardless of query params
  const deleted = cache.deleteMatching(`**/users/${req.params.id}*`);
  console.log(`${deleted} cache entries removed`);

  res.json({ ok: true });
});

Glob rules:

PatternBehaviour
*Matches any sequence of characters within a single path segment (does not cross /)
**Matches any sequence of characters across path segments (crosses /)
?Matches any single character except /

deleteMatching returns the number of entries removed and emits a delete event for each one.

Event hooks

const cache = memorize({ ttl: 30_000 });

cache.on('set', (e) => {
  console.log(`[cache] stored ${e.key} — expires in ${e.expiresAt ? e.expiresAt - Date.now() : '∞'}ms`);
});

cache.on('delete', (e) => {
  console.log(`[cache] deleted ${e.key}`);
});

cache.on('expire', (e) => {
  console.log(`[cache] expired ${e.key}`);
});

Inspect the cache

cache.get('/users');   // CacheInfo | null — single entry
cache.getAll();        // Record<string, CacheInfo> — all active entries

CacheInfo shape:

{
  key: string;
  body: unknown;
  statusCode: number;
  contentType: string;
  expiresAt: number | null;
  remainingTtl: number | null; // ms until expiry, null if no TTL
  hits: number;                // total times this key was requested
}

hits starts at 1 on the initial cache miss (when the entry is stored) and increments by 1 on every subsequent cache hit. It resets to 1 if the entry is evicted and re-cached.

// Example: monitoring hot keys
const entries = cache.getAll();
for (const [key, info] of Object.entries(entries)) {
  console.log(`${key}${info.hits} hits`);
}
// /users        → 42 hits
// /products     → 7 hits

Clear the cache

cache.delete('/users');                  // remove one entry
cache.deleteMatching('**/users/*');      // remove all /users/* entries
cache.clear();                           // remove all entries

API Reference

memorize(options?)

Creates a cache instance. Returns a Memorize object.

OptionTypeDefaultDescription
ttlnumberundefinedTime-to-live in milliseconds. Omit for no expiry.

cache(options?)

Returns an Express RequestHandler middleware. Can override the global TTL.

OptionTypeDefaultDescription
ttlnumberglobal ttlTTL override for this specific route.

Cache management

MethodSignatureDescription
get(key: string) => CacheInfo | nullReturns info for a cached key.
getAll() => Record<string, CacheInfo>Returns all active cache entries.
delete(key: string) => booleanRemoves a single entry. Returns false if not found.
deleteMatching(pattern: string) => numberRemoves all entries matching a glob pattern. Returns the count removed.
clear() => voidRemoves all entries.

Events

EventPayloadWhen
set{ type, key, body, statusCode, contentType, expiresAt }A response is stored
delete{ type, key }cache.delete(), cache.deleteMatching(), or cache.clear() is called
expire{ type, key }TTL timer fires or lazy expiry is detected

Response Headers

HeaderValueDescription
X-CacheHITResponse served from cache
X-CacheMISSResponse computed and stored
X-CacheBYPASSCache skipped — noCache: true was set for this route

Behavior

  • Only GET requests are cached. All other methods bypass the middleware entirely.
  • Only responses with a 2xx status code are stored.
  • Each call to cache() returns an independent middleware handler, but all handlers created from the same memorize() instance share the same store.
  • Two separate memorize() calls produce independent stores.

License

MIT

Keywords

express

FAQs

Package last updated on 31 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts