Skip to content
Warlock.js v4

File Cache Driver

The File Cache Driver stores cached data as files on disk. Each cache key is a directory containing a cache.json file.

  • Local development
  • Need persistence across restarts, but don’t want to set up Redis
  • Small to medium-sized cache needs
  • Caching API responses, config, or data that should survive restarts
  • Environments where Redis is not available
  • Slower than memory or Redis for large caches
  • Not suitable for distributed/multi-server setups
  • Manual cleanup of expired files only happens on access
  • update() and merge() throw CacheUnsupportedError — the file driver has no file-lock primitive yet. Use the memory or redis driver for atomic read-modify-write, or wait for v2.1.
  • cache.list() works but is O(n) with disk I/O per operation. Avoid large lists on the file driver.
src/config/cache.ts
import { env } from "@mongez/dotenv";
import { join } from "path";
import { CacheConfigurations, FileCacheDriver } from "@warlock.js/cache";
const cacheConfigurations: CacheConfigurations = {
drivers: {
file: FileCacheDriver,
},
default: env("CACHE_DRIVER", "file"),
options: {
file: {
globalPrefix: "my-app",
ttl: "1d",
directory: join(process.cwd(), "storage", "cache"), // absolute path
fileName: "data.json",
},
},
};
export default cacheConfigurations;
OptionTypeDefaultDescription
directorystring | FunctionstoragePath("cache")Directory for cache files
fileNamestring | Function"cache.json"File name for cache data
globalPrefixstring | FunctionundefinedGlobal prefix for all cache keys
ttlnumber | string0Default TTL — seconds or a duration string ("1h", "7d"). 0 means no expiration.

The directory option should be an absolute path to ensure consistent behavior regardless of where the process is started:

import { join } from "path";
{
directory: join(process.cwd(), "storage", "cache"), // Absolute path
// OR
directory: join(__dirname, "..", "storage", "cache"), // From project root
// OR
directory: "/var/cache/myapp", // Explicit absolute path
// OR
directory: () => join(process.cwd(), "cache", environment()), // Dynamic absolute path
}
{
fileName: "data.json", // Custom file name
// OR
fileName: () => `cache-${Date.now()}.json`, // Dynamic file name
}
{
globalPrefix: "myapp", // Static prefix
// OR
globalPrefix: () => `app-${environment()}`, // Dynamic prefix
}
{
ttl: 0, // no expiration (default)
// OR
ttl: 3600, // 1 hour, numeric seconds
// OR
ttl: "1h", // human-readable duration string
// OR
ttl: "7d", // 7 days
}
import { cache } from "@warlock.js/cache";
await cache.set("products.555.details", { name: "Monitor", specs: { size: "27inch" } }, "1h");
const details = await cache.get("products.555.details");

The file driver creates a directory structure like this:

/var/cache/myapp/ (or your specified directory)
├── myapp.products.555.details/
│ └── cache.json
├── myapp.users.42.profile/
│ └── cache.json
└── myapp.cart.session-xyz/
└── cache.json

Each cache entry is stored in its own directory with a JSON file containing the data and metadata.

  • Expired cache is only removed when accessed.
  • For automatic cleanup, consider a background job or use Redis.
  • Cache not persistent? Check your directory path and permissions.
  • Performance issues? For large caches, use Redis or Memory drivers.

Not supported. cache.set(k, v, { vector }) and cache.similar(...) throw CacheUnsupportedError. Use a memory driver (dev) or the pg driver with vector config (production).