Caching

MoroJS provides intelligent caching capabilities to improve performance and reduce load on your APIs. Learn about different caching strategies and implementations.

Route-Level Caching

Basic Route Caching (Chainable API)

typescript

1import { createApp, z } from '@morojs/moro';
2
3const app = createApp();
4
5// Caching with chainable API
6app.get('/users')
7  .query(z.object({
8    limit: z.coerce.number().min(1).max(100).default(10),
9    search: z.string().optional()
10  }))
11  .cache({ ttl: 60, key: 'users-list' }) // Cache for 60 seconds
12  .handler((req, res) => {
13    // This will only run if not cached
14    const users = getAllUsers(req.query);
15    return { success: true, data: users };
16  });
17
18// Dynamic cache keys with parameters
19app.get('/users/:id')
20  .cache({ ttl: 300, key: (req) => `user-${req.params.id}` }) // 5 minutes
21  .handler((req, res) => {
22    const user = getUserById(req.params.id);
23    return { success: true, data: user };
24  });
25
26// Configuration-driven caching
27app.post('/users-config')
28  .cache({ ttl: app.getConfig().modules.cache.defaultTtl })
29  .handler((req, res) => {
30    return createUser(req.body);
31  });

Cache Configuration

typescript

1// View current cache configuration
2app.get('/config', (req, res) => {
3  const config = app.getConfig();
4  return {
5    cache: {
6      enabled: config.modules.cache.enabled,
7      defaultTtl: config.modules.cache.defaultTtl,
8      maxSize: config.modules.cache.maxSize,
9      strategy: config.modules.cache.strategy
10    }
11  };
12});
13
14// Simple cache example with different TTLs
15app.get('/data/fast')
16  .cache({ ttl: 30 }) // 30 seconds for frequently changing data
17  .handler(() => getFastChangingData());
18
19app.get('/data/slow')
20  .cache({ ttl: 3600 }) // 1 hour for stable data
21  .handler(() => getSlowChangingData());

Caching Features

  • • Simple TTL-based caching
  • • Dynamic cache keys
  • • Configuration-driven settings
  • • Automatic cache invalidation on TTL expiry
  • • Memory-based storage (default)

External Caching Solutions

For advanced caching features like Redis integration, cache invalidation strategies, and distributed caching, integrate external caching libraries.

Redis Integration Example

typescript

1import { createApp } from '@morojs/moro';
2import Redis from 'redis';
3
4const app = createApp();
5const redis = Redis.createClient({
6  url: process.env.REDIS_URL
7});
8
9await redis.connect();
10
11// Custom caching middleware with Redis
12const redisCache = (ttl) => {
13  return async (req, res, next) => {
14    const cacheKey = `cache:${req.method}:${req.path}`;
15    
16    try {
17      const cached = await redis.get(cacheKey);
18      if (cached) {
19        return res.json(JSON.parse(cached));
20      }
21      
22      // Store original send function
23      const originalSend = res.json;
24      res.json = function(data) {
25        // Cache the response
26        redis.setEx(cacheKey, ttl, JSON.stringify(data));
27        return originalSend.call(this, data);
28      };
29      
30      next();
31    } catch (error) {
32      console.error('Cache error:', error);
33      next();
34    }
35  };
36};
37
38// Use Redis caching middleware
39app.get('/users', redisCache(300), (req, res) => {
40  const users = getAllUsers();
41  return { success: true, data: users };
42});

Cache Invalidation

Tag-Based Invalidation

typescript

1import { getCache } from '@morojs/moro';
2
3app.post('/users', {
4  body: CreateUserSchema,
5  handler: async ({ body }) => {
6    const user = await createUser(body);
7    
8    // Invalidate user-related caches
9    const cache = getCache();
10    await cache.invalidateByTag(['users']);
11    
12    return { user };
13  }
14});
15
16app.put('/users/:id', {
17  params: UserParamsSchema,
18  body: UpdateUserSchema,
19  handler: async ({ params, body }) => {
20    const user = await updateUser(params.id, body);
21    
22    // Invalidate specific user cache
23    const cache = getCache();
24    await cache.invalidateByTag([`user:${params.id}`, 'users']);
25    
26    return { user };
27  }
28});

Manual Cache Management

typescript

1import { getCache } from '@morojs/moro';
2
3const cache = getCache();
4
5// Set cache manually
6await cache.set('key', { data: 'value' }, { ttl: '1h' });
7
8// Get from cache
9const cached = await cache.get('key');
10
11// Delete specific key
12await cache.delete('key');
13
14// Clear all cache
15await cache.clear();
16
17// Get cache stats
18const stats = await cache.getStats();
19console.log(`Hit rate: ${stats.hitRate}%`);

Next Steps