# MemoryStorage, FileStorage, and Custom Storage in LINEJS: A Complete Guide

> Explore MemoryStorage, FileStorage, and custom storage in LINEJS. Understand their differences and choose the best strategy for your application's data persistence needs. Learn more now.

- Repository: [Evex  Developers/linejs](https://github.com/evex-dev/linejs)
- Tags: how-to-guide
- Published: 2026-03-01

---

**LINEJS provides three storage strategies—MemoryStorage for ephemeral in-memory caching, FileStorage for local JSON persistence, and custom storage implementations for external backends—all implementing the abstract `BaseStorage` interface defined in [`packages/linejs/base/storage/base.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/base.ts).**

The LINEJS library (evex-dev/linejs) manages authentication tokens, encryption keys, and conversation caches through a pluggable storage layer. Understanding the difference between MemoryStorage, FileStorage, and custom storage options ensures your bot or client retains critical data across restarts or distributes state across multiple instances.

## Understanding the Storage Architecture

The storage system in LINEJS revolves around a single abstract class that defines the contract between the client and its persistence layer.

### The BaseStorage Contract

In [`packages/linejs/base/storage/base.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/base.ts), the `BaseStorage` abstract class defines five required methods that every implementation must support:

```typescript
export abstract class BaseStorage {
  abstract set(key: Storage["Key"], value: Storage["Value"]): Promise<void>;
  abstract get(key: Storage["Key"]): Promise<Storage["Value"] | undefined>;
  abstract delete(key: Storage["Key"]): Promise<void>;
  abstract clear(): Promise<void>;
  abstract migrate(storage: BaseStorage): Promise<void>;
}

```

Any storage implementation—built-in or custom—must extend this class and handle these operations for the key-value pairs that LINEJS uses to maintain session state.

## Built-in Storage Implementations

LINEJS ships with two concrete implementations that cover most development scenarios.

### MemoryStorage (Volatile In-Memory)

Located in [`packages/linejs/base/storage/memory.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/memory.ts), **MemoryStorage** stores data in a private `Map` object held in RAM. This implementation is the default when you create a client without specifying storage options, as noted in the source comments of [`packages/linejs/client/login.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/client/login.ts).

```typescript
export class MemoryStorage extends BaseStorage {
  private data = new Map<Storage["Key"], Storage["Value"]>();
  // Methods operate directly on this.data
}

```

Data persists only for the lifetime of the Node.js or Deno process. When the process exits, authentication tokens and encryption keys disappear, forcing a fresh login on the next execution.

### FileStorage (Persistent JSON)

For CLI tools and long-running bots that survive process restarts, **FileStorage** (in [`packages/linejs/base/storage/file.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/file.ts)) serializes the storage state to a JSON file on disk using the Node.js `fs` module.

```typescript
export class FileStorage extends BaseStorage {
  constructor(private path: string, extendData?: string) {
    // Initializes file path and optional extension data
  }
  // Reads/writes JSON on every get/set operation
}

```

This approach ensures your auth tokens and keys persist between runs without requiring re-authentication, though it is limited to single-instance deployments.

## Implementing Custom Storage

When built-in options do not match your infrastructure requirements, you can implement **custom storage** by extending `BaseStorage` yourself.

### When to Use Custom Storage

Choose a custom implementation when you need:

- **Distributed state**: Share auth tokens across multiple instances using Redis or DynamoDB
- **Encryption at rest**: Encrypt data before persisting to cloud storage
- **Browser compatibility**: Use IndexedDB or `localStorage` in browser environments
- **Enterprise policies**: Integrate with existing secret management systems

### Example: Browser LocalStorage Implementation

The repository provides a working example in [`example/storage/local.ts`](https://github.com/evex-dev/linejs/blob/main/example/storage/local.ts) that demonstrates how to wrap the browser's `localStorage` API:

```typescript
import type { BaseStorage, Storage } from "@evex/linejs/storage";

export class LocalStorage implements BaseStorage {
  private readonly prefix = "linejs:";

  async set(key: Storage["Key"], value: Storage["Value"]) {
    localStorage.setItem(this.prefix + key, JSON.stringify(value));
  }

  async get(key: Storage["Key"]) {
    const raw = localStorage.getItem(this.prefix + key);
    return raw ? JSON.parse(raw) : undefined;
  }

  async delete(key: Storage["Key"]) {
    localStorage.removeItem(this.prefix + key);
  }

  async clear() {
    localStorage.clear();
  }

  async migrate(storage: BaseStorage) {
    // Copy existing entries to another storage if needed
  }
}

```

## How to Configure Storage in Your Client

Pass your chosen storage instance through the `storage` property in client options, as documented in [`docs/docs/client-options.md`](https://github.com/evex-dev/linejs/blob/main/docs/docs/client-options.md).

### Using MemoryStorage (Default)

```typescript
import { loginWithPassword } from "@evex/linejs";

const client = await loginWithPassword({
  email: "you@example.com",
  password: "secure-password",
});
// Storage defaults to MemoryStorage; data is lost when the process exits

```

### Using FileStorage for Persistence

```typescript
import { loginWithAuthToken } from "@evex/linejs";
import { FileStorage } from "@evex/linejs/storage";

const client = await loginWithAuthToken("YOUR_AUTHTOKEN", {
  storage: new FileStorage("./linejs-storage.json"),
});
// Tokens persist in ./linejs-storage.json between restarts

```

### Using Custom Storage

```typescript
import { loginWithAuthToken } from "@evex/linejs";
import { LocalStorage } from "./path/to/local.ts";

const client = await loginWithAuthToken("YOUR_AUTHTOKEN", {
  storage: new LocalStorage(),
});

```

## Summary

- **MemoryStorage** ([`packages/linejs/base/storage/memory.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/memory.ts)) provides zero-config, high-speed storage that clears when the process exits—ideal for one-off scripts and testing.
- **FileStorage** ([`packages/linejs/base/storage/file.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/file.ts)) persists data to a local JSON file using Node.js `fs`, making it perfect for CLI tools and single-instance bots.
- **Custom storage** requires implementing the `BaseStorage` abstract class from [`packages/linejs/base/storage/base.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/base.ts), enabling integration with Redis, cloud databases, or browser storage like the `LocalStorage` example in [`example/storage/local.ts`](https://github.com/evex-dev/linejs/blob/main/example/storage/local.ts).

## Frequently Asked Questions

### What happens if I don't specify a storage option when creating a LINEJS client?

If you omit the `storage` parameter, the client defaults to `MemoryStorage` according to the implementation in [`packages/linejs/client/login.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/client/login.ts). Your authentication tokens and encryption keys remain in RAM only, disappearing completely when the Node.js or Deno process terminates, which forces re-authentication on the next run.

### Can I switch from MemoryStorage to FileStorage without losing my current session?

No, because `MemoryStorage` does not persist data to disk. When you switch to `FileStorage`, you must provide a valid auth token to initialize the client. However, once running with `FileStorage`, the library automatically saves new tokens and keys to the specified JSON file path for future restarts.

### Is FileStorage suitable for production environments with multiple server instances?

FileStorage is not recommended for horizontally scaled deployments. Because it reads from and writes to a single local filesystem path, concurrent access from multiple processes can cause race conditions or data corruption. For production clusters, implement a custom storage backend using Redis, PostgreSQL, or another distributed store that handles concurrent access safely.

### What data does LINEJS actually store in these storage backends?

LINEJS stores authentication tokens, device registration information, encryption keys for E2EE conversations, and internal caching metadata. The specific keys and value types are defined by the `Storage` interface referenced in [`packages/linejs/base/storage/base.ts`](https://github.com/evex-dev/linejs/blob/main/packages/linejs/base/storage/base.ts), ensuring type safety across all implementations.