Every bot
Runtime
- Node.js 22 or later, and your app is ESM (
"type": "module"inpackage.json, or.mjsfiles). The packages ship no CommonJS build. - A process manager restarts the bot when it exits: PM2, systemd,
Docker
restart: unless-stoppedor your orchestrator. See Deployment. - Graceful shutdown: on
SIGTERM/SIGINTcallawait bot.stop({ drain: true, timeout: '15s' })so replies in flight are sent and recorded before the process exits (Graceful shutdown). - Pin your versions (commit the lockfile). While the packages are in beta, read the migration pages before each upgrade.
State
- A persistent store. The default
MemoryStorekeeps everything in RAM. UseSQLiteStorefor one process orRedisStorefor several (Persistent store). - Pass the store instance:
store: new SQLiteStore({ file }). A string such asstore: 'sqlite'is accepted for compatibility but still creates aMemoryStore. - Multi-step flows are
.persistent(), so a user in the middle of a flow resumes it after a restart (Flows). - On Node.js 24.19 or later, use
better-sqlite313 withSQLiteStore(why). - Volumes and backups: the WhatsApp session folder (
sessions/) and the data folder (data/) are mounted on persistent disk and backed up together (Backups).
Secrets
- Tokens, API keys and webhook secrets come from the environment (or your secret manager), never from the source tree. The framework reads no environment variable by itself: you map them to the provider options (Environment variables).
sessions/,.env,*.dband*.qr.pngare in.gitignoreand never copied into a Docker image.
Webhooks (Cloud API, Telegram webhook, Twilio…)
- Served over HTTPS, with the channel’s signature check configured
(
appSecret,webhookSecret…). Never setallowUnsignedWebhooks: truein production (Security). - The signature is checked on the raw body: do not put a JSON body parser in front of the webhook route (Webhook server).
Observability
- Logs: pass your own pino
logger(or keep the built-in one, which logs atwarn). Chat and sender ids are hashed in log lines by default (logIds: 'hash'); keep it that way outside local debugging. - Errors: listen to
bot.on('error', …)and send them to your error tracker. - Health and metrics: expose a liveness/readiness endpoint and
bot.metrics()in Prometheus format (Health checks, Operations).
Channel limits
- WhatsApp on Baileys: keep the provider’s rate limiter on and avoid unsolicited bulk sends (Rate limiting).
- Cloud API: free-form replies only within the 24-hour window; use templates outside it (WhatsApp 24h window).
- Message log growth: the persistent stores keep every message unless
you set
maxMessagesPerChat(Persistent store).
When you need more
All of these are opt-in: without the option, the bot runs exactly as before.
Which packages are published
The npm packages (36) are@botmesh/core; the channels @botmesh/baileys,
@botmesh/meta, @botmesh/telegram, @botmesh/messenger, @botmesh/instagram,
@botmesh/discord, @botmesh/evolution, @botmesh/wppconnect, @botmesh/twilio,
@botmesh/gupshup, @botmesh/gohighlevel and @botmesh/email; the stores
@botmesh/sqlite-store, @botmesh/redis-store, @botmesh/postgres-store,
@botmesh/mysql-store and @botmesh/mongo-store; the infrastructure @botmesh/http,
@botmesh/graph-core, @botmesh/wa-gateway-kit, @botmesh/server, @botmesh/events
and @botmesh/otel; the plugins @botmesh/ai, @botmesh/rag, @botmesh/voice,
@botmesh/nlu, @botmesh/dialogflow, @botmesh/chatwoot, @botmesh/tickets and
@botmesh/moderation; and the tooling @botmesh/flow-schema, @botmesh/mcp,
eslint-plugin-botmesh and create-botmesh. All 36 are on npm. Ten of them were first published during the alpha (core, baileys, meta, telegram, sqlite-store, redis-store, ai,
http, graph-core and create-botmesh); the other 26 shipped for the first time with the beta.
Some pages also describe packages that live only in the
repository for now
(the TikTok channel, @botmesh/manager, the sandbox…). Each of those pages says so. Plan a
production deployment on the published ones.
Before each release of your bot
- Tests pass with
createTestBot/MockProvider(Testing). - The store files or databases are backed up before upgrading
@botmesh/sqlite-store: a newer schema version cannot be opened by an older release (Schema versions). - With replicas, every replica runs a version that understands the options
you turn on (for example
coordination.handover.flows: 'forward').