# Preloading Models at Startup and Managing Persistent Cache Strategies in Transformers.js

> Learn to preload Transformers.js models at startup and manage persistent cache with custom backends. Optimize your application's model loading performance efficiently.

- Repository: [Hugging Face/transformers.js](https://github.com/huggingface/transformers.js)
- Tags: performance
- Published: 2026-03-03

---

**Preloading models at startup in Transformers.js involves using `ModelRegistry.get_pipeline_files()` to identify required assets, then eagerly loading them via `ModelRegistry.get_model_files()` or pipeline initialization, while persistent caching is handled through configurable backends in [`src/utils/cache.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/cache.js) that respect `env.cacheDir` and cache flags.**

When building production web applications with **Hugging Face Transformers.js**, eliminating cold-start latency requires strategic preloading and persistent storage of model weights. The library implements a sophisticated caching architecture centered on [`src/utils/hub.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/hub.js) for file retrieval and [`src/utils/cache.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/cache.js) for backend selection, enabling granular control over model asset persistence across Node.js, Deno, Bun, and browser environments.

## How Model Loading and Caching Work Under the Hood

### The Loading Pipeline

When you call `pipeline()` or load a model directly, the library orchestrates file retrieval through a specific chain of operations in [`src/utils/hub.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/hub.js). The `getModelFile()` function builds resource paths and delegates to `loadResourceFile()`, which first checks for cached assets via `checkCachedResource()` before initiating network requests. After fetching, `storeCachedResource()` persists the data to the selected backend. This flow ensures that subsequent requests for identical model files—whether ONNX weights, tokenizers, or configuration files—resolve instantly from local storage.

### Cache Backend Selection

The `getCache()` function in [`src/utils/cache.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/cache.js) dynamically selects a storage implementation based on environment variables defined in [`src/env.js`](https://github.com/huggingface/transformers.js/blob/main/src/env.js):

- **Filesystem Cache (`FileCache`)**: Activated when `env.useFSCache` is `true` and filesystem access is available (Node/Deno/Bun), defaulting to `./.cache/` relative to the project root.
- **Browser Cache API**: Activated when `env.useBrowserCache` is `true` and the Cache API is available, storing data under the key defined in `env.cacheKey` (default: `'transformers-cache'`).
- **Custom Cache**: Activated when `env.useCustomCache` is `true` and `env.customCache` is assigned an object implementing the `match` and `put` interface.

You can override default locations before any model requests:

```javascript
import { env } from '@huggingface/transformers';

// Node.js: custom directory
env.cacheDir = '/var/lib/myapp/models';

// Browser: custom storage key
env.cacheKey = 'my-production-cache';

```

### ModelRegistry Discovery API

The [`src/utils/model_registry/ModelRegistry.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/model_registry/ModelRegistry.js) class provides static methods essential for preloading models at startup:

- **`ModelRegistry.get_pipeline_files(task, modelId, options)`**: Returns the complete list of files required for a specific pipeline task (model weights, tokenizer files, generation configs).
- **`ModelRegistry.is_pipeline_cached(task, modelId)`**: Reports whether all required files exist in the current cache backend.
- **`ModelRegistry.clear_cache(modelId, options)`**: Removes cached files for a specific model configuration.

## Preloading Models at Startup

### Eager Loading with ModelRegistry

To eliminate first-inference latency, resolve the file list for your target model and trigger downloads before user interaction. This pattern ensures the cache is primed:

```javascript
import { ModelRegistry } from '@huggingface/transformers';

async function preloadGenerationModel() {
  const modelId = 'Xenova/gpt2-onnx';
  const task = 'text-generation';
  const options = { dtype: 'q4', device: 'webgpu' };

  // 1. Discover required files
  const files = await ModelRegistry.get_pipeline_files(task, modelId, options);

  // 2. Download all files in parallel (cache side-effect)
  await Promise.all(
    files.map((file) => ModelRegistry.get_model_files(modelId, options))
  );

  // 3. Verify cache status
  const status = await ModelRegistry.is_pipeline_cached(task, modelId);
  console.log('Cache primed:', status.allCached);
}

```

Calling `ModelRegistry.get_model_files()` triggers the underlying `getModelFile()` logic for each required asset, storing them in the configured cache without loading the full model into memory.

### Preloading via Pipeline Initialization

Alternatively, instantiate the pipeline at application startup and retain the instance. The first `pipeline()` call downloads and caches all necessary files:

```javascript
let generator;

async function initializePipeline() {
  generator = await pipeline('text-generation', 'Xenova/gpt2-onnx', {
    dtype: 'q4',
    device: 'webgpu',
    progress_callback: (info) => {
      console.log(`[${info.status}] ${info.file}`);
    },
  });
}

// Execute at startup
await initializePipeline();
// Subsequent calls use cached files
const output = await generator('Hello world');

```

## Managing Persistent Cache Strategies

### Configuring Cache Behavior

Control persistence and storage location through the `env` object before any model operations:

| Setting | Default | Description |
|---------|---------|-------------|
| `env.cacheDir` | `./.cache/` (Node) | Filesystem path for model storage |
| `env.useFSCache` | `true` (if FS available) | Enable filesystem persistence |
| `env.useBrowserCache` | `true` (if Cache API available) | Enable browser Cache API |
| `env.cacheKey` | `'transformers-cache'` | Browser cache storage key |

These flags are evaluated at runtime by `getCache()` in [`src/utils/cache.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/cache.js), allowing dynamic configuration based on deployment environment.

### Clearing Cached Files

To force fresh downloads or reclaim storage, use the `ModelRegistry` clearing methods:

```javascript
// Clear specific model configuration
await ModelRegistry.clear_cache('Xenova/gpt2-onnx', { dtype: 'q4' });

// Clear only files for a specific pipeline task
await ModelRegistry.clear_pipeline_cache('text-generation', 'Xenova/gpt2-onnx');

```

Both methods return statistics including `filesDeleted` and `filesCached`, enabling UI feedback for cache management interfaces.

### Implementing Custom Cache Backends

For advanced scenarios like IndexedDB versioning or eviction policies, implement the `CacheInterface`:

```javascript
class IndexedDBCache {
  async match(key) {
    // Return Response, FileResponse, or string path
  }
  
  async put(key, response, progressCallback) {
    // Store in IndexedDB
  }
}

import { env } from '@huggingface/transformers';
env.useCustomCache = true;
env.customCache = new IndexedDBCache();

```

Once registered, all model file operations route through your custom implementation, bypassing the default filesystem and browser caches.

## Complete Startup Script Example

This pattern combines configuration, preloading, and pipeline initialization for a production-ready setup:

```javascript
import { pipeline, ModelRegistry, env } from '@huggingface/transformers';

// Configure cache before any model operations
env.cacheDir = process.env.MODEL_CACHE_DIR || './.cache';
env.useFSCache = true;

const MODELS = [
  { task: 'text-generation', id: 'Xenova/gpt2-onnx', opts: { dtype: 'q4' } },
  { task: 'image-classification', id: 'Xenova/vit-base-patch16-224', opts: {} },
];

// Preload all models to warm the cache
async function warmCache() {
  for (const { task, id, opts } of MODELS) {
    const files = await ModelRegistry.get_pipeline_files(task, id, opts);
    await Promise.all(
      files.map(() => ModelRegistry.get_model_files(id, opts))
    );
    console.log(`Cached ${id} for ${task}`);
  }
}

// Initialize reusable pipelines
const pipelines = {};
async function initPipelines() {
  for (const { task, id, opts } of MODELS) {
    pipelines[task] = await pipeline(task, id, opts);
  }
}

// Startup sequence
await warmCache();
await initPipelines();
// Application ready: all models cached and loaded

```

## Summary

- **Preloading models at startup** requires calling `ModelRegistry.get_pipeline_files()` to identify assets, then `ModelRegistry.get_model_files()` to populate the cache before user requests.
- **Persistent cache strategies** are configured via `env.cacheDir`, `env.useFSCache`, `env.useBrowserCache`, and `env.useCustomCache` in [`src/env.js`](https://github.com/huggingface/transformers.js/blob/main/src/env.js), with backends implemented in [`src/utils/cache.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/cache.js).
- **Cache verification** is available through `ModelRegistry.is_pipeline_cached()`, returning an `allCached` boolean and per-file status.
- **Cache invalidation** uses `ModelRegistry.clear_cache()` or `ModelRegistry.clear_pipeline_cache()` to remove specific models or task configurations.
- **Custom storage** implements the `match`/`put` interface and registers via `env.customCache` when `env.useCustomCache` is enabled.

## Frequently Asked Questions

### How do I check if a model is already cached before preloading?

Call `await ModelRegistry.is_pipeline_cached(task, modelId)` or `await ModelRegistry.is_cached(modelId, options)` to verify cache status without triggering downloads. These methods return an object containing `allCached` (boolean) and detailed file status, allowing you to skip preloading for already-cached assets.

### Can I use different cache locations for different models?

While `env.cacheDir` sets a global filesystem path for Node.js environments, you cannot specify per-model cache directories directly. However, you can implement a custom cache backend via `env.customCache` that routes different model IDs to different storage locations based on your own logic in the `match` and `put` methods.

### What happens if I disable all cache flags in `env`?

Setting `env.useFSCache = false`, `env.useBrowserCache = false`, and `env.useCustomCache = false` forces `getCache()` in [`src/utils/cache.js`](https://github.com/huggingface/transformers.js/blob/main/src/utils/cache.js) to return a null cache. In this mode, every model request fetches fresh data from the Hugging Face Hub or local filesystem, eliminating persistence but ensuring you always retrieve the latest model versions.

### How do I force a specific model to re-download?

Use `await ModelRegistry.clear_cache(modelId, options)` with the exact `options` object (including `dtype`, device settings, etc.) used during the original download. This removes the cached entries from the active backend. The next request for that model configuration will fetch fresh files from the remote Hub.