
Product
Socket for Jira Is Now Available
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.
secure-store-redis
Advanced tools
Encrypt and store data in Redis. Uses AES-256-GCM encryption with unique IVs per entry.
npm install secure-store-redis
import SecureStore, { SecretValidator } from "secure-store-redis";
const store = new SecureStore({
uid: "myApp",
secret: SecretValidator.generate(),
redis: { url: "redis://localhost:6379" },
});
await store.connect();
await store.save("key", { foo: "bar" });
const data = await store.get("key");
await store.disconnect();
new SecureStore(config: SecureStoreConfig)
| Option | Type | Required | Description |
|---|---|---|---|
uid | string | Yes | Unique prefix for Redis keys (e.g., "myApp", "myApp:sessions") |
secret | string | Yes | 32-character encryption secret. Use SecretValidator.generate(). |
redis | RedisOptions | { url: string } | { client: Redis | Cluster } | Yes | Redis connection config or existing client |
allowWeakSecrets | boolean | No | Bypass secret strength validation (default: false) |
You can pass your own ioredis Redis or Cluster client instead of connection options. This enables connection sharing, pre-configured clients, and integration with existing Redis infrastructure.
import { Redis } from "ioredis";
import SecureStore, { SecretValidator } from "secure-store-redis";
const redis = new Redis({ host: "localhost", port: 6379 });
const store = new SecureStore({
uid: "myApp",
secret: SecretValidator.generate(),
redis: { client: redis },
});
await store.connect();
await store.save("key", "value");
await store.disconnect();
// Your client is still connected - you manage its lifecycle
console.log(redis.status); // "ready"
await redis.quit();
import { Cluster } from "ioredis";
import SecureStore, { SecretValidator } from "secure-store-redis";
const cluster = new Cluster([
{ host: "node1", port: 6379 },
{ host: "node2", port: 6379 },
]);
const store = new SecureStore({
uid: "myApp",
secret: SecretValidator.generate(),
redis: { client: cluster },
});
await store.connect();
Multiple SecureStore instances can share a single Redis connection:
const redis = new Redis();
const sessionsStore = new SecureStore({
uid: "sessions",
secret: sessionSecret,
redis: { client: redis },
});
const cacheStore = new SecureStore({
uid: "cache",
secret: cacheSecret,
redis: { client: redis },
});
await sessionsStore.connect();
await cacheStore.connect();
// Both stores use the same connection
// Disconnecting either store does NOT close the Redis client
Important notes:
disconnect() will NOT close the Redis connection - you are responsible for calling redis.quit() when doneconnect() will wait for it to be readyconnect() will throw a ConnectionErrorconnect(): Promise<void>Connect to Redis. Must be called before other operations.
save<T>(key: string, data: T, postfix?: string): Promise<void>Encrypt and store data.
get<T>(key: string, postfix?: string): Promise<T | null>Retrieve and decrypt data. Returns null if not found or decryption fails.
delete(key: string, postfix?: string): Promise<number>Delete data. Returns count of deleted keys.
disconnect(client?: Redis): Promise<void>Close Redis connection. Optionally pass a specific Redis client to disconnect.
namespace<TSchema>(name: string): TypedNamespace<TSchema>Create a typed namespace for organizing data. See Namespaces for details.
client: RedisClient | undefined - The underlying ioredis client (Redis or Cluster)isConnected: boolean - Connection statusNamespaces allow you to organize data with type-safe operations. Each namespace acts as an isolated partition within the same store.
const store = new SecureStore({
uid: "myApp",
secret: SecretValidator.generate(),
redis: { url: "redis://localhost:6379" },
});
await store.connect();
// Create a typed namespace
interface UserSchema {
profile: { name: string; age: number };
settings: { theme: string; notifications: boolean };
}
const users = store.namespace<UserSchema>("users");
// Type-safe operations
await users.save("profile", { name: "John", age: 30 });
await users.save("settings", { theme: "dark", notifications: true });
const profile = await users.get("profile"); // { name: string; age: number } | null
const settings = await users.get("settings");
await users.delete("profile");
Each namespace provides the same core operations as the store:
get<K>(key: K): Promise<T[K] | null>save<K>(key: K, data: T[K]): Promise<void>delete<K>(key: K): Promise<number>Data in different namespaces is completely isolated:
const users = store.namespace("users");
const sessions = store.namespace("sessions");
await users.save("data", "user-data");
await sessions.save("data", "session-data");
await users.get("data"); // "user-data"
await sessions.get("data"); // "session-data"
await store.get("data"); // null (root store is separate)
Utility class for generating and validating encryption secrets.
generate(length?: number): stringGenerate a cryptographically secure secret. Defaults to 32 characters if no length specified.
validate(secret: string): { valid: boolean; reason?: string }Validate secret strength against security requirements.
Secrets must:
All errors extend SecureStoreError and include a code property for programmatic handling.
import {
SecureStoreError,
ConnectionError,
EncryptionError,
ValidationError,
} from "secure-store-redis";
try {
await store.connect();
} catch (err) {
if (err instanceof ConnectionError) {
console.error(`Connection failed (${err.code}):`, err.message);
// err.code === "CONNECTION_ERROR"
}
}
| Error Class | Code | When Thrown |
|---|---|---|
ConnectionError | CONNECTION_ERROR | Redis connection failures |
EncryptionError | ENCRYPTION_ERROR | Encryption/decryption failures |
ValidationError | VALIDATION_ERROR | Invalid configuration, keys, or data |
SecretValidator.generate() for cryptographically secure secretsuid values per application/environment to prevent data collisions| Change | Migration |
|---|---|
uid required | Add explicit uid to constructor |
secret required | Use SecretValidator.generate() or provide your own |
connect() required | Call await store.connect() before use |
| AES-256-GCM | Re-encrypt existing data (format changed) |
| Secret validation | Use strong secrets or set allowWeakSecrets: true |
// v3.x
const store = new SecureStore({ redis: { url: "..." } });
await store.init();
// v4.0
const store = new SecureStore({
uid: "myApp",
secret: SecretValidator.generate(),
redis: { url: "..." },
});
await store.connect();
Full TypeScript support with exported types:
import SecureStore, {
SecureStoreConfig,
TypedNamespace,
RedisClient,
SecretValidator,
SecureStoreError,
ConnectionError,
EncryptionError,
ValidationError,
} from "secure-store-redis";
MIT
FAQs
A simple wrapper to encrypt and decrypt data stored in Redis
The npm package secure-store-redis receives a total of 74 weekly downloads. As such, secure-store-redis popularity was classified as not popular.
We found that secure-store-redis demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket for Jira lets teams turn alerts into Jira tickets with manual creation, automated ticketing rules, and two-way sync.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.