> ## Documentation Index
> Fetch the complete documentation index at: https://zapo.to/llms.txt
> Use this file to discover all available pages before exploring further.

# Produção & deploy

> Rode o zapo de forma confiável em produção: persistência durável, shutdown gracioso, múltiplas sessões, estratégia de reconexão e os ajustes que importam.

O `zapo` foi feito para cargas de trabalho longevas e multi-sessão. Esta página reúne as decisões operacionais que importam quando você passa do protótipo local.

<h2 id="persist-credentials">
  Persista as credenciais (não refaça o pareamento)
</h2>

Sessões de produção **precisam** usar uma [store](/pt-br/concepts/stores) durável para os domínios `auth` e Signal, além de um **`sessionId` estável** entre reinícios. A store em memória perde tudo ao sair, forçando um novo pareamento a cada boot.

```ts theme={null}
const client = new WaClient({ store, sessionId: 'tenant-42' }, logger)
```

Trocar o `sessionId` deixa as credenciais anteriores órfãs — trate-o como a chave durável de um dispositivo/conta.

<h2 id="choose-a-store-backend">
  Escolha um backend de store
</h2>

| Backend                                            | Melhor para                                                        |
| -------------------------------------------------- | ------------------------------------------------------------------ |
| `@zapo-js/store-sqlite`                            | Processo único / host único — a opção local mais simples e rápida. |
| `@zapo-js/store-postgres` · `@zapo-js/store-mysql` | Múltiplos hosts, operações relacionais, backups gerenciados.       |
| `@zapo-js/store-redis`                             | Cache de baixa latência + persistência.                            |
| `@zapo-js/store-mongo`                             | Deployments orientados a documentos.                               |

Você pode misturar backends por domínio (ex.: `auth`/`signal` no Postgres, caches no Redis). Veja [Instalação](/pt-br/installation#add-a-storage-backend) e a [referência de stores](/pt-br/reference/stores).

<h2 id="graceful-shutdown">
  Shutdown gracioso
</h2>

Chame `disconnect()` (nunca `logout()`) no shutdown — ele descarrega os dados pendentes de [write-behind](/pt-br/concepts/configuration#write-behind-persistence) e fecha o socket **sem** desvincular o dispositivo, então o próximo boot retoma a partir da store.

```ts theme={null}
for (const signal of ['SIGINT', 'SIGTERM'] as const) {
  process.on(signal, async () => {
    await client.disconnect()
    process.exit(0)
  })
}
```

<Warning>
  `logout()` desvincula o dispositivo no servidor e limpa o estado armazenado — força um novo pareamento completo. Use-o apenas para desconectar permanentemente, nunca como hook de shutdown.
</Warning>

<h2 id="run-many-sessions">
  Rode muitas sessões
</h2>

Uma única store pode conter muitas contas independentes, cada uma indexada por `sessionId`. Crie um `WaClient` por conta:

```ts theme={null}
const clients = tenants.map((id) => new WaClient({ store, sessionId: id }, logger))
await Promise.all(clients.map((c) => c.connect()))
```

Cada client pareia, reconecta e emite eventos de forma independente. Reserve memória/CPU por sessão (cada uma mantém estado Signal e caches em memória) e faça sharding entre processos/hosts conforme escala — um processo por sessão é o modelo de isolamento mais simples. Veja [Deploys multi-sessão](/pt-br/guides/multi-session) para o guia operacional completo.

<h2 id="tune-for-throughput">
  Ajuste para throughput
</h2>

* **Write-behind** agrupa as escritas de mensagens/threads/contatos fora do hot path. Ajuste `writeBehind.maxPendingKeys` / `maxWriteConcurrency` / `flushTimeoutMs` ao seu banco. ([config](/pt-br/concepts/configuration#write-behind-persistence))
* **History sync** (`history.enabled`) é ligado por padrão e adiciona um download inicial grande. Defina como `false` se você não persiste mailbox/threads/contacts; use `requireFullSync` deliberadamente.
* **Bots que não devem aparecer online**: `markOnlineOnConnect` é `false` por padrão, então bots ficam invisíveis ao conectar. Passe `true` apenas quando quiser uma presença "online" visível.
* **Timeouts** (`iqTimeoutMs`, `keepAliveIntervalMs`, `deadSocketTimeoutMs`, …) vêm com padrões de produção — sobrescreva só com motivo. ([config](/pt-br/concepts/configuration#timeouts))

<h2 id="reconnection--error-policy">
  Política de reconexão & erros
</h2>

O `zapo` **não** reconecta sozinho — assuma a política. Ligue um loop de backoff ([Reconexão](/pt-br/guides/reconnection)) e classifique as falhas ([Erros & desconexões](/pt-br/guides/errors)) para parar em razões fatais (`banned`, `not_authorized`, logout) em vez de martelar o servidor.

<h2 id="logging">
  Logging
</h2>

Use um logger estruturado em produção:

```ts theme={null}
const logger = await createPinoLogger({ level: 'info', pretty: false })
```

`pretty: false` emite linhas JSON adequadas a agregadores de log. Caia para `debug` / `trace` só ao investigar.

<h2 id="security--versioning">
  Segurança & versionamento
</h2>

* **Credenciais são segredos.** `WaAuthCredentials` contém as chaves do dispositivo — se você as persistir fora da store embutida, criptografe em repouso. ([Autenticação](/pt-br/concepts/authentication#credentials))
* **Nunca habilite `dangerous.*`** em produção — essas flags desabilitam verificações de segurança. ([config](/pt-br/concepts/configuration#dangerous-options))
* **Versionamento.** O `zapo` é `1.0` e segue [versionamento semântico](https://semver.org) — breaking changes só acontecem em um novo major. Use um range de versão ou lockfile como de costume, e revise o changelog antes de upgrades de major.
