Pular para o conteúdo principal
Cada pacote de backend exporta uma factory create*Store que você passa para uma entrada de backends do createStore. Todos os backends implementam os mesmos contratos de store por domínio, então trocar de backend é uma mudança de config, não de código.

SQLite

@zapo-js/store-sqlitecreateSqliteStore(config).
Informe exatamente um entre path e connection. Com path, a biblioteca abre (e faz ref-count d)e sua própria connection e a fecha em store.destroy(). Com connection, você é dono do ciclo de vida — store.destroy() mantém a connection aberta para você continuar usando em outros lugares.

Use sua própria connection

Compartilhe um único handle do SQLite com o resto da sua aplicação abrindo-o você mesmo com openSqliteConnection e passando via connection:
Requer a peer dependency better-sqlite3.

PostgreSQL

@zapo-js/store-postgrescreatePostgresStore(config).
Também exporta createPgPool e ensurePgMigrations. Requer a peer dependency pg.

MySQL

@zapo-js/store-mysqlcreateMysqlStore(config).
Também exporta createMysqlPool e ensureMysqlMigrations. Requer a peer dependency mysql2.

Chunking de inserts em lote

batchInsertChunkSize limita quantas linhas os backends PostgreSQL e MySQL agrupam em um único INSERT multi-linha em escritas em lote — sessões do Signal, identidades remotas, distribuições de sender key, geração de prekeys e os caminhos upsertBatch de message/thread/contact usados pela write-behind persistence. O valor é arredondado para baixo até a potência de dois mais próxima internamente (500 → 256, 1000 → 512, …), e cada lote é decomposto em sub-chunks de potência de dois. Isso mantém o conjunto de prepared statements distintos por conexão limitado a log2(chunkSize) + 1 independentemente de como N varia entre chamadas — importante para ficar abaixo do cache do cliente mysql2 e da quota max_prepared_stmt_count do MySQL, e para manter o cache de statements nomeados do pg estável. Mantenha o padrão a menos que benchmarks do seu workload mostrem benefício. Aumente para envios em grupo de alto fanout sustentados; reduza se os limites do seu banco forem apertados.

Redis

@zapo-js/store-rediscreateRedisStore(config).

TTL por domínio do store

Domínios de store persistentes nunca expiram por padrão. Defina storeTtlMs.<domínio>Ms para o Redis prunar as chaves daquele domínio automaticamente — implementado como PEXPIRE em cada escrita, sem precisar de cleanup em background. Qualquer domínio deixado de fora permanece persistente (comportamento byte-idêntico ao anterior).
Duas semânticas, por tipo de domínio:
auth não tem botão de TTL de propósito: expirar credenciais de login deslogaria o device. Escolha um TTL de crypto maior que sua pior janela de ociosidade — uma sessão ociosa além dessa janela evicta as chaves de Signal / app-state e força um novo handshake ou re-sync. Valores ttlMs não-positivos são rejeitados na construção.
Requer a peer dependency ioredis.

MongoDB

@zapo-js/store-mongocreateMongoStore(config).
Requer a peer dependency mongodb. Escritas em lote usam { ordered: false } para que upserts independentes rodem em paralelo — uma falha por documento não aborta o resto do lote.

Expiração e limpeza de cache

Os quatro domínios de cache (retry, groupMetadata, deviceList, messageSecret) usam um TTL definido em cacheTtlMs. A forma como entradas expiradas são removidas varia por backend:
No PostgreSQL e MySQL, sem startCleanup suas tabelas de cache crescem monotonicamente. Leituras continuam ignorando linhas expiradas (dado obsoleto nunca é servido), mas o uso de disco cresce sem limite. Inicie um poller por session id.
cleanup.intervalMs tem default 60_000 (60s). result.destroy() para todos os pollers iniciados por ele, então chamar poller.stop() manualmente só é útil se você quiser interromper a limpeza antes de derrubar o backend. No MongoDB, a latência de ~60s do TTL monitor faz entradas de cache poderem persistir um pouco além do TTL configurado. Aceitável para groupMetadata/deviceList; troque pelo Redis se precisar de eviction mais agressivo.

Misturando backends

O createStore permite que cada domínio escolha um backend por nome, então você pode combiná-los:
Todo domínio de persistência deve ser listado quando backends é definido — veja Stores para a regra e os valores aceitos ('<backend>', 'memory', 'none').
Última modificação em 30 de junho de 2026