npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zapo-js/store-redis

v1.1.0

Published

Redis store provider for zapo-js

Readme

@zapo-js/store-redis

Redis-backed persistent store for zapo-js. Best fit when you already run Redis for caching and want stateless app instances that can share WhatsApp session state through a network database.

Built on ioredis. All 11 persistent domains and 4 cache domains live under a single key namespace (keyPrefix controls it). Cache TTLs are enforced natively by Redis - no background cleanup job needed.

Install

npm install @zapo-js/store-redis ioredis

ioredis is a peer dependency.

Quick start

import { createStore, WaClient } from 'zapo-js'
import { createRedisStore } from '@zapo-js/store-redis'

const store = createStore({
    backends: {
        redis: createRedisStore({
            redis: { host: '127.0.0.1', port: 6379 },
            keyPrefix: 'wa:'
        })
    },
    providers: {
        auth: 'redis',
        signal: 'redis',
        senderKey: 'redis',
        appState: 'redis',
        privacyToken: 'redis'
    }
})

const client = new WaClient({ store, sessionId: 'default' })

Config

createRedisStore(config) accepts:

| Field | Description | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | | redis | A live ioredis instance or RedisOptions for a new client. When the store builds the client itself, destroy() will quit() it for you. | | keyPrefix | String prepended to every key (e.g. 'wa:', 'tenant-A:'). | | cacheTtlMs | TTLs for retry, groupMetadata, deviceList, messageSecret (Redis EX/PEXPIRE). | | storeTtlMs | Opt-in TTLs for the otherwise-persistent store domains (see Store TTLs). Any domain left unset stays persistent. |

The return value extends WaStoreBackend with { redis, destroy } so you can reuse the same connection elsewhere and shut it down cleanly on app exit.

Store TTLs

The persistent domains never expire by default. storeTtlMs lets you put an optional Redis-native TTL on individual domains (applied as PEXPIRE on each write - no cleanup job), with two semantics depending on the domain kind:

createRedisStore({
    redis: { host: '127.0.0.1', port: 6379 },
    storeTtlMs: {
        // Data domains - expire N ms after the last write (history/retention):
        messagesMs: 30 * 24 * 60 * 60 * 1000,
        threadsMs: 30 * 24 * 60 * 60 * 1000,
        contactsMs: 30 * 24 * 60 * 60 * 1000,
        privacyTokenMs: 7 * 24 * 60 * 60 * 1000,
        // Crypto & session domains - sliding TTL, refreshed on read too, so
        // only idle sessions are evicted (active ones never expire):
        signalMs: 90 * 24 * 60 * 60 * 1000,
        preKeyMs: 90 * 24 * 60 * 60 * 1000,
        sessionMs: 90 * 24 * 60 * 60 * 1000,
        identityMs: 90 * 24 * 60 * 60 * 1000,
        senderKeyMs: 90 * 24 * 60 * 60 * 1000,
        appStateMs: 90 * 24 * 60 * 60 * 1000
    }
})
  • Data (messagesMs, threadsMs, contactsMs, privacyTokenMs): TTL is refreshed on write only - keys expire a fixed window after their last update.
  • Crypto & session (signalMs, preKeyMs, sessionMs, identityMs, senderKeyMs, appStateMs): TTL is refreshed on read and write, so an actively used session keeps its keys alive and only genuinely idle sessions are reclaimed.
  • auth has no TTL knob on purpose: expiring login credentials would log the device out. It always persists.

Set a crypto/session TTL short relative to how often a session connects at your own risk - an idle window longer than the TTL evicts the Signal / app-state keys and forces a re-handshake or re-sync on next use.

Notes

  • Pass an externally-owned Redis when you want to control its lifecycle yourself (clusters, sentinel, etc.) - the library will not call quit() on it.
  • Keys are JSON-encoded blobs. Migrating to a different backend later means draining via the in-memory store or doing a one-shot SCAN copy.
  • For multi-region deployments, use the same keyPrefix across instances and let Redis replication handle session sharing.

See the main zapo-js docs for the full store contract.