Caching in TypeScript: Redis, Memcached, and Built-in Solutions: from A to Z
\n\nCaching is one of the key tools for improving the performance of web applications and services. In the TypeScript and Node.js ecosystem, developers can choose between powerful external systems (Redis, Memcached) and lightweight built-in solutions. In this article, we will break down all three approaches, provide practical code examples in TypeScript, and help you choose the optimal strategy for your project.
\n\nWhy is caching needed in TypeScript?
\nCaching allows you to reduce server response time, decrease the load on databases and external APIs, and minimize delays for repeated requests. In TypeScript, running on top of Node.js, caching is especially useful for:
\n- \n
- storing results of expensive computations; \n
- caching responses from external APIs; \n
- saving user sessions; \n
- reducing the number of database queries. \n
1. Built-in solutions for caching in TypeScript
\nFor small projects or prototypes, you can use Node.js built-in tools without installing additional packages.
\n\n1.1. Using Map
\nThe simplest way is a Map object or a plain object. However, such a cache only lives in the memory of a single process and is lost upon restart.
// Simple cache based on Map\nclass SimpleCache<T> {\n private cache = new Map<string, T>();\n\n get(key: string): T | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, value: T): void {\n this.cache.set(key, value);\n }\n\n clear(): void {\n this.cache.clear();\n }\n}\n\n// Usage example\nconst cache = new SimpleCache<string>();\ncache.set('user:1', 'Alice');\nconsole.log(cache.get('user:1')); // Alice\n\n1.2. Cache with TTL (Time-To-Live)
\nA more advanced version is a cache with automatic deletion of entries after a specified time.
\n// Cache with TTL\nclass TtlCache<T> {\n private cache = new Map<string, { value: T; expiry: number }>();\n\n get(key: string): T | undefined {\n const item = this.cache.get(key);\n if (!item) return undefined;\n if (Date.now() > item.expiry) {\n this.cache.delete(key);\n return undefined;\n }\n return item.value;\n }\n\n set(key: string, value: T, ttlMs: number): void {\n this.cache.set(key, {\n value,\n expiry: Date.now() + ttlMs,\n });\n }\n}\n\n// Example\nconst ttlCache = new TtlCache<number>();\nttlCache.set('price', 100, 5000); // lives for 5 seconds\nsetTimeout(() => console.log(ttlCache.get('price')), 6000); // undefined\n\n2. Caching with Redis in TypeScript
\nRedis is a popular in-memory data store that supports advanced data structures, pub/sub, and persistence. For TypeScript, the ioredis package is used.
2.1. Installation and connection
\nnpm install ioredis\nnpm install @types/ioredis --save-dev\nimport Redis from 'ioredis';\n\nconst redis = new Redis({\n host: 'localhost',\n port: 6379,\n});\n\nredis.on('connect', () => console.log('Connected to Redis'));\nredis.on('error', (err) => console.error('Redis error', err));\n\n2.2. Basic set/get operations
\n// Save a value\nawait redis.set('user:1:name', 'Alice');\n\n// Get a value\nconst name = await redis.get('user:1:name');\nconsole.log(name); // Alice\n\n// Set TTL (in seconds)\nawait redis.setex('session:123', 3600, 'active');\n\n2.3. Working with objects (JSON)
\n// Save an object\nconst user = { id: 1, name: 'Alice', email: 'alice@example.com' };\nawait redis.set('user:1', JSON.stringify(user));\n\n// Read and parse\nconst r