Socket
Book a DemoInstallSign in
Socket

tiny-lru

Package Overview
Dependencies
Maintainers
1
Versions
113
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tiny-lru

A high-performance, lightweight LRU cache. Built for developers who need fast caching without compromising on features.

latest
Source
npmnpm
Version
11.4.5
Version published
Weekly downloads
1.2M
2.53%
Maintainers
1
Weekly downloads
Β 
Created
Source

πŸš€ Tiny LRU

npm version Node.js Version License Build Status Test Coverage

A high-performance, lightweight LRU cache for JavaScript with strong UPDATE performance and competitive SET/GET/DELETE, and a compact bundle size. Built for developers who need fast caching without compromising on features.

πŸ“¦ Installation

npm install tiny-lru
# or
yarn add tiny-lru  
# or
pnpm add tiny-lru

Requirements: Node.js β‰₯12

⚑ Quick Start

import {lru} from "tiny-lru";

// Create cache and start using immediately
const cache = lru(100); // Max 100 items
cache.set('user:123', {name: 'John', age: 30});
const user = cache.get('user:123'); // {name: 'John', age: 30}

// With TTL (5 second expiration)
const tempCache = lru(50, 5000);
tempCache.set('session', 'abc123'); // Automatically expires after 5 seconds

πŸ“‘ Table of Contents

✨ Features & Benefits

Why Choose Tiny LRU?

  • πŸ”„ Strong Cache Updates - Excellent performance in update-heavy workloads
  • πŸ“¦ Compact Bundle - Just ~2.2 KiB minified for a full-featured LRU library
  • βš–οΈ Balanced Performance - Competitive across all operations with O(1) complexity
  • ⏱️ TTL Support - Optional time-to-live with automatic expiration
  • πŸ”„ Method Chaining - Fluent API for better developer experience
  • 🎯 TypeScript Ready - Full TypeScript support with complete type definitions
  • 🌐 Universal Compatibility - Works seamlessly in Node.js and browsers
  • πŸ›‘οΈ Production Ready - Battle-tested and reliable

Benchmark Comparison (Mean of 5 runs)

LibrarySET ops/secGET ops/secUPDATE ops/secDELETE ops/sec
tiny-lru404,7531,768,4491,703,716298,770
lru-cache326,2211,069,061878,858277,734
quick-lru591,6831,298,487935,481359,600
mnemonist412,4672,478,7782,156,6900

Notes:

  • Mean values computed from the Performance Summary across 5 consecutive runs of npm run benchmark:comparison.
  • mnemonist lacks a compatible delete method in this harness, so DELETE ops/sec is 0.
  • Performance varies by hardware, Node.js version, and workload patterns; run the provided benchmarks locally to assess your specific use case.
  • Environment: Node.js v24.5.0, macOS arm64.

πŸ“Š Performance Deep Dive

When to Choose Tiny LRU

βœ… Perfect for:

  • Frequent cache updates - Leading UPDATE performance
  • Mixed read/write workloads - Balanced across all operations
  • Bundle size constraints - Compact library with full features
  • Production applications - Battle-tested with comprehensive testing

Running Your Own Benchmarks

# Run all performance benchmarks
npm run benchmark:all

# Individual benchmark suites
npm run benchmark:modern     # Comprehensive Tinybench suite
npm run benchmark:perf       # Performance Observer measurements
npm run benchmark:comparison # Compare against other LRU libraries

πŸš€ Getting Started

Installation

npm install tiny-lru
# or
yarn add tiny-lru
# or  
pnpm add tiny-lru

Quick Examples

import {lru} from "tiny-lru";

// Basic cache
const cache = lru(100);
cache.set('key1', 'value1')
     .set('key2', 'value2')
     .set('key3', 'value3');

console.log(cache.get('key1')); // 'value1'
console.log(cache.size); // 3

// With TTL (time-to-live)
const cacheWithTtl = lru(50, 30000); // 30 second TTL
cacheWithTtl.set('temp-data', {important: true});
// Automatically expires after 30 seconds

const resetCache = lru(25, 10000, true);
resetCache.set('session', 'user123');
// Because resetTtl is true, TTL resets when you set() the same key again

CDN Usage (Browser)

<!-- ES Modules -->
<script type="module">
  import {lru, LRU} from 'https://cdn.skypack.dev/tiny-lru';
  const cache = lru(100);
</script>

<!-- UMD Bundle (global: window.lru) -->
<script src="https://unpkg.com/tiny-lru/dist/tiny-lru.umd.js"></script>
<script>
  const {lru, LRU} = window.lru;
  const cache = lru(100);
  // or: const cache = new LRU(100);
</script>

TypeScript Usage

import {lru, LRU} from "tiny-lru";

// Type-safe cache
const cache = lru<string>(100);
// or: const cache: LRU<string> = lru<string>(100);
cache.set('user:123', 'John Doe');
const user: string | undefined = cache.get('user:123');

// Class inheritance
class MyCache extends LRU<User> {
  constructor() {
    super(1000, 60000, true); // 1000 items, 1 min TTL, reset TTL on set
  }
}

Configuration Options

Factory Function

import {lru} from "tiny-lru";

const cache = lru(max, ttl = 0, resetTtl = false);

Parameters:

  • max {Number} - Maximum number of items (0 = unlimited, default: 1000)
  • ttl {Number} - Time-to-live in milliseconds (0 = no expiration, default: 0)
  • resetTtl {Boolean} - Reset TTL when updating existing items via set() (default: false)

Class Constructor

import {LRU} from "tiny-lru";

const cache = new LRU(1000, 60000, true); // 1000 items, 1 min TTL, reset TTL on set

Best Practices

// 1. Size your cache appropriately
const cache = lru(1000); // Not too small, not too large

// 2. Use meaningful keys
cache.set(`user:${userId}:profile`, userProfile);
cache.set(`product:${productId}:details`, productDetails);

// 3. Handle cache misses gracefully
function getData(key) {
  const cached = cache.get(key);
  if (cached !== undefined) {
    return cached;
  }
  
  // Fallback to slower data source
  const data = expensiveOperation(key);
  cache.set(key, data);
  return data;
}

// 4. Clean up when needed
process.on('exit', () => {
  cache.clear(); // Help garbage collection
});

Optimization Tips

  • Cache Size: Keep cache size reasonable (1000-10000 items for most use cases)
  • TTL Usage: Only use TTL when necessary; it adds overhead
  • Key Types: String keys perform better than object keys
  • Memory: Call clear() when done to help garbage collection

πŸ’‘ Real-World Examples

API Response Caching

import {lru} from "tiny-lru";

class ApiClient {
  constructor() {
    this.cache = lru(100, 300000); // 5 minute cache
  }

  async fetchUser(userId) {
    const cacheKey = `user:${userId}`;
    
    // Return cached result if available
    if (this.cache.has(cacheKey)) {
      return this.cache.get(cacheKey);
    }

    // Fetch from API and cache
    const response = await fetch(`/api/users/${userId}`);
    const user = await response.json();
    
    this.cache.set(cacheKey, user);
    return user;
  }
}

Function Memoization

import {lru} from "tiny-lru";

function memoize(fn, maxSize = 100) {
  const cache = lru(maxSize);
  
  return function(...args) {
    const key = JSON.stringify(args);
    
    if (cache.has(key)) {
      return cache.get(key);
    }
    
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

// Usage
const expensiveCalculation = memoize((n) => {
  console.log(`Computing for ${n}`);
  return n * n * n;
}, 50);

console.log(expensiveCalculation(5)); // Computing for 5 -> 125
console.log(expensiveCalculation(5)); // 125 (cached)

Session Management

import {lru} from "tiny-lru";

class SessionManager {
  constructor() {
    // 30 minute TTL, with resetTtl enabled for set()
    this.sessions = lru(1000, 1800000, true);
  }

  createSession(userId, data) {
    const sessionId = this.generateId();
    const session = {
      userId,
      data,
      createdAt: Date.now()
    };
    
    this.sessions.set(sessionId, session);
    return sessionId;
  }

  getSession(sessionId) {
    // get() does not extend TTL; to extend, set the session again when resetTtl is true
    return this.sessions.get(sessionId);
  }

  endSession(sessionId) {
    this.sessions.delete(sessionId);
  }
}

πŸ”— Interoperability

Compatible with Lodash's memoize function cache interface:

import _ from "lodash";
import {lru} from "tiny-lru";

_.memoize.Cache = lru().constructor;
const memoized = _.memoize(myFunc);
memoized.cache.max = 10;

πŸ› οΈ Development

Testing

Tiny LRU maintains 100% test coverage with comprehensive unit and integration tests.

# Run all tests with coverage
npm test

# Run tests with verbose output
npm run mocha

# Lint code
npm run lint

# Full build (lint + build)
npm run build

Test Coverage: 100% coverage across all modules

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 lru.js   |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------

Contributing

Quick Start for Contributors

# Clone and setup
git clone https://github.com/avoidwork/tiny-lru.git
cd tiny-lru
npm install

# Run tests
npm test

# Run linting
npm run lint

# Run benchmarks  
npm run benchmark:all

# Build distribution files
npm run build

Development Workflow

  • Fork the repository on GitHub
  • Clone your fork locally
  • Create a feature branch: git checkout -b feature/amazing-feature
  • Develop your changes with tests
  • Test thoroughly: npm test && npm run lint
  • Commit using conventional commits: git commit -m "feat: add amazing feature"
  • Push to your fork: git push origin feature/amazing-feature
  • Submit a Pull Request

Contribution Guidelines

  • Code Quality: Follow ESLint rules and existing code style
  • Testing: Maintain 100% test coverage for all changes
  • Documentation: Update README.md and JSDoc for API changes
  • Performance: Benchmark changes that could impact performance
  • Compatibility: Ensure Node.js β‰₯12 compatibility
  • Commit Messages: Use Conventional Commits format

πŸ“– API Reference

Factory Function

lru(max, ttl, resetTtl)

Creates a new LRU cache instance using the factory function.

Parameters:

  • max {Number} - Maximum number of items to store (default: 1000; 0 = unlimited)
  • ttl {Number} - Time-to-live in milliseconds (default: 0; 0 = no expiration)
  • resetTtl {Boolean} - Reset TTL when updating existing items via set() (default: false)

Returns: {LRU} New LRU cache instance

Throws: {TypeError} When parameters are invalid

import {lru} from "tiny-lru";

// Basic cache
const cache = lru(100);

// With TTL
const cacheWithTtl = lru(50, 30000); // 30 second TTL

// With resetTtl enabled for set()
const resetCache = lru(25, 10000, true);

// Validation errors
lru(-1);          // TypeError: Invalid max value
lru(100, -1);     // TypeError: Invalid ttl value  
lru(100, 0, "no"); // TypeError: Invalid resetTtl value

Properties

first

{Object|null} - Item in first (least recently used) position

const cache = lru();
cache.first; // null - empty cache

last

{Object|null} - Item in last (most recently used) position

const cache = lru();
cache.last; // null - empty cache

max

{Number} - Maximum number of items to hold in cache

const cache = lru(500);
cache.max; // 500

resetTtl

{Boolean} - Whether to reset TTL when updating existing items via set()

const cache = lru(500, 5*6e4, true);
cache.resetTtl; // true

size

{Number} - Current number of items in cache

const cache = lru();
cache.size; // 0 - empty cache

ttl

{Number} - TTL in milliseconds (0 = no expiration)

const cache = lru(100, 3e4);
cache.ttl; // 30000

Methods

clear()

Removes all items from cache.

Returns: {Object} LRU instance

cache.clear();

delete(key)

Removes specified item from cache.

Parameters:

  • key {String} - Item key

Returns: {Object} LRU instance

cache.set('key1', 'value1');
cache.delete('key1');
console.log(cache.has('key1')); // false

entries([keys])

Returns array of cache items as [key, value] pairs.

Parameters:

  • keys {Array} - Optional array of specific keys to retrieve (defaults to all keys)

Returns: {Array} Array of [key, value] pairs

cache.set('a', 1).set('b', 2);
console.log(cache.entries()); // [['a', 1], ['b', 2]]
console.log(cache.entries(['a'])); // [['a', 1]]

evict()

Removes the least recently used item from cache.

Returns: {Object} LRU instance

cache.set('old', 'value').set('new', 'value');
cache.evict(); // Removes 'old' item

expiresAt(key)

Gets expiration timestamp for cached item.

Parameters:

  • key {String} - Item key

Returns: {Number|undefined} Expiration time (epoch milliseconds) or undefined if key doesn't exist

const cache = new LRU(100, 5000); // 5 second TTL
cache.set('key1', 'value1');
console.log(cache.expiresAt('key1')); // timestamp 5 seconds from now

get(key)

Retrieves cached item and promotes it to most recently used position.

Parameters:

  • key {String} - Item key

Returns: {*} Item value or undefined if not found/expired

Note: get() does not reset or extend TTL. TTL is only reset on set() when resetTtl is true.

cache.set('key1', 'value1');
console.log(cache.get('key1')); // 'value1'
console.log(cache.get('nonexistent')); // undefined

has(key)

Checks if key exists in cache (without promoting it).

Parameters:

  • key {String} - Item key

Returns: {Boolean} True if key exists and is not expired

cache.set('key1', 'value1');
console.log(cache.has('key1')); // true
console.log(cache.has('nonexistent')); // false

keys()

Returns array of all cache keys in LRU order (first = least recent).

Returns: {Array} Array of keys

cache.set('a', 1).set('b', 2);
cache.get('a'); // Move 'a' to most recent
console.log(cache.keys()); // ['b', 'a']

set(key, value)

Stores item in cache as most recently used.

Parameters:

  • key {String} - Item key
  • value {*} - Item value

Returns: {Object} LRU instance

cache.set('key1', 'value1')
     .set('key2', 'value2')
     .set('key3', 'value3');

setWithEvicted(key, value)

Stores item and returns evicted item if cache was full.

Parameters:

  • key {String} - Item key
  • value {*} - Item value

Returns: {Object|null} Evicted item {key, value, expiry, prev, next} or null

const cache = new LRU(2);
cache.set('a', 1).set('b', 2);
const evicted = cache.setWithEvicted('c', 3); // evicted = {key: 'a', value: 1, ...}
if (evicted) {
  console.log(`Evicted: ${evicted.key}`, evicted.value);
}

values([keys])

Returns array of cache values.

Parameters:

  • keys {Array} - Optional array of specific keys to retrieve (defaults to all keys)

Returns: {Array} Array of values

cache.set('a', 1).set('b', 2);
console.log(cache.values()); // [1, 2]
console.log(cache.values(['a'])); // [1]

πŸ“„ License

Copyright (c) 2025 Jason Mulligan
Licensed under the BSD-3 license.

Keywords

LRU

FAQs

Package last updated on 13 Aug 2025

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