LiteBot

Operations

This chapter covers running LiteBot day to day: where the logs are, what NODE_ENV changes, which health probes to poll, how language model providers fail and recover, what a restart does, how Redis fits in, what reloads without a restart, capacity, backups and a safe deploy routine. It assumes the binary under pm2 from Quickstart: binary.

Logs

LiteBot logs through winston. Every line goes to standard output, so pm2 captures it. With NODE_ENV=production, LiteBot also writes log files under the working directory.

Where What Rotation
pm2 logs litebot (files ~/.pm2/logs/litebot-out.log and litebot-error.log) Everything at LOG_LEVEL and above pm2 install pm2-logrotate
logs/error.log Errors only, production mode None built in; use logrotate
logs/combined.log Everything, production mode Same
Variable Default Meaning
LOG_LEVEL debug Winston level: error, warn, info, debug. .env.example sets info; use info in production, because debug logs message previews for every turn
LOG_FILE unset Replaces both file names above with one path. Both file transports then write to the same file, so error lines appear twice. .env.example sets logs/app.log

Console lines are coloured and look like info: POST /api/chat 200 812ms {...}. Every HTTP request gets one such line with method, path, status and duration. Grep on the words, not on the line start.

pm2 logs litebot --lines 200 --nostream | grep -E "error|unhealthy|Circuit breaker"

Lines worth knowing:

Line contains Meaning Do this
JWT_SECRET must be defined and at least 32 characters long Startup refused. Fix JWT_SECRET in .env.
MongoDB connection error then Failed to start server MongoDB unreachable at boot; the process exits and pm2 restarts it. Check MONGODB_URI and the database host.
Loaded N bots and M tools Boot finished loading configuration. Compare N and M with what you expect. A bot file that fails validation is skipped and logged.
Provider <name> marked unhealthy after 3 failures That provider is out of rotation. See Provider health and recovery.
All providers unhealthy, attempting with first available provider No provider is marked healthy. Same section.
Circuit breaker OPEN for <name> Calls to that provider are being rejected for 60 seconds (only with ENABLE_CIRCUIT_BREAKER=true). Check the provider's key, credit and status page.
Redis connection failed - using memory fallback Redis is not reachable; sessions use memory and MongoDB. Normal if you do not run Redis.
GEMINI_API_KEY is not set but N bot(s) have voice.enabled=true Voice sessions for those bots will fail at setup. Set GEMINI_API_KEY or turn voice off on those bots.
Voice WS upgrade rejected A /voice connection had no valid token or API key. See Voice.
Forced shutdown after timeout Shutdown took more than 10 seconds. See Restarts and shutdown.

What NODE_ENV changes

NODE_ENV defaults to development when unset. Many installations keep it at development because production mode switches off the reload endpoints and tightens the rate limit. Decide deliberately:

Behaviour development (or unset) production
Rate limit on /api per client IP 500 requests per 5 minutes 100 requests per 15 minutes
Log files under logs/ No Yes
Error replies from the error handler The real message (plus a stack trace when set to development exactly) Something went wrong!
Bot and prompt file watching On Only with ENABLE_HOT_RELOAD=true
Tool file watching On Off
POST /api/bots/reload, POST /api/tools/reload Work Return 403

API_RATE_LIMIT replaces the request count in either mode; the window stays 5 or 15 minutes. The limit applies to all /api routes except /api/documents and /api/collections, and it counts per client address (trust proxy is set to one hop, so behind a reverse proxy it uses X-Forwarded-For). A voice gateway or a WhatsApp integration sends all its traffic from one address: in production mode, raise API_RATE_LIMIT well above its peak turns per 15 minutes, or its requests get HTTP 429. WebSocket traffic is not rate limited.

Health probes

Probe Auth Checks Healthy reply Unhealthy reply
GET /health None MongoDB ping 200 {"status":"healthy"} 503 {"status":"unhealthy"}
GET /health/ready None MongoDB ping; collections conversations, bots, leads, support_tickets exist; auto-dialer initialised when enabled 200 {"ready":true} 503 with ready: false and a message
GET /health/detail Admin JWT or admin API key MongoDB, Redis, vector database, auto-dialer 200, see below 401, 403 or 503

LiteBot creates the four required collections at boot, so /health/ready fails only when the database or the auto-dialer is broken.

curl -s http://127.0.0.1:3345/health/detail -H 'Authorization: Bearer <token>'
{
  "status": "healthy",
  "timestamp": "2026-10-24T07:19:33.032Z",
  "uptime": 86234.5,
  "environment": "development",
  "version": "1.0.0",
  "services": {
    "mongodb": "healthy",
    "redis": { "status": "disabled", "message": "Redis not available - using memory fallback", "connected": false },
    "vectorDb": { "provider": "vectra", "status": "healthy" },
    "autoDialer": { "initialized": false, "enabled": false, "lastError": null, "initializedAt": null }
  }
}

Poll /health every 30 to 60 seconds and alert on anything but 200. /health does not test the language model providers: a server whose provider keys are all dead still answers healthy. Watch the provider status below as well, or send a scheduled test chat.

Provider health and recovery

LiteBot tracks each provider registered from .env. After 3 consecutive failed requests it marks the provider unhealthy and logs marked unhealthy. While a provider is unhealthy, a bot that asks for it is served by another healthy provider: DEFAULT_LLM_PROVIDER first, then the others in registration order. This substitution happens even with DISABLE_PROVIDER_FALLBACK=true; that setting only controls the extra fallback attempt made by the circuit breaker. If every provider is unhealthy, LiteBot tries the first registered one anyway. One successful request marks a provider healthy again.

Check the state:

curl -s http://127.0.0.1:3345/api/bots/providers/status -H 'Authorization: Bearer <token>'
{
  "success": true,
  "data": {
    "providers": {
      "gemini": { "healthy": false, "consecutiveFailures": 3, "lastError": "Request failed with status code 402", "provider": "GeminiProvider" },
      "openrouter": { "healthy": true, "consecutiveFailures": 0, "provider": "OpenRouterProvider" }
    },
    "available": ["gemini", "openrouter"],
    "total": 2,
    "healthy": 1
  }
}

Bring a provider back after you fix its key or credit:

Action Endpoint Who
Health-check every provider and mark each healthy or unhealthy POST /api/bots/providers/health-check Admin
Send one test message to one provider POST /api/admin/providers/<name>/test Admin
Re-create all providers from the loaded settings POST /api/admin/providers/reinitialize Admin
Restart pm2 restart litebot --update-env Shell
curl -s -X POST http://127.0.0.1:3345/api/bots/providers/health-check -H 'Authorization: Bearer <token>'

Newer builds also re-probe an unhealthy provider on their own: once per PROVIDER_RETRY_MS (default 60000), one real request is sent to it, and if it succeeds the provider returns to rotation (log line Probing unhealthy provider <name>). These builds also drop the bot's model name when another provider stands in, logging <name> serving with its default model. In older builds an unhealthy provider stays out until one of the actions above or a restart, and the stand-in provider receives the original bot's model name, which another provider usually rejects. If you run an older build, include the health-check call in your incident routine.

Per-tenant provider keys are outside this rotation: a tenant's own provider never falls back to the global keys. Reinitialising does not re-read .env; edits to .env need a restart. Provider settings are in LLM providers.

Restarts and shutdown

On SIGTERM or SIGINT (what pm2 restart and pm2 stop send), LiteBot closes chat and voice WebSockets, which ends every live voice session, stops its timers and background queue (up to 10 seconds), stops accepting HTTP connections and exits. If that takes longer than 10 seconds it forces the exit. pm2 waits only 1.6 seconds by default before it kills the process; give it the full window:

pm2 delete litebot
pm2 start ./litebot --name litebot --cwd /opt/litebot --kill-timeout 10000
pm2 save

An unhandled error or rejected promise also triggers this shutdown, and pm2 then starts a fresh process. Repeated restarts in pm2 list (the restart counter) point at such errors; read the lines before each Received ... starting graceful shutdown.

What survives a restart: chat sessions and their history, which are stored in MongoDB and reloaded when the next message arrives with the same sessionId. What does not: live voice sessions, in-flight chat turns, the in-memory caches, and provider health state (every provider starts healthy).

Sessions and Redis

Redis is optional. LiteBot always tries to connect to REDIS_HOST:REDIS_PORT (default localhost:6379); if that fails, or after 3 failed reconnect attempts, it logs a warning and uses memory plus MongoDB. Session lookups go through an in-process cache, then Redis when connected, then memory, then MongoDB.

Variable Default Meaning
REDIS_HOST, REDIS_PORT, REDIS_PASSWORD, REDIS_DB localhost, 6379, none, 0 Connection
REDIS_SESSION_TTL 3600 Seconds a session stays in Redis
REDIS_WRITE_THROUGH off unless true true stores sessions in Redis first and writes them to MongoDB in the background. .env.example sets true
SESSION_IDLE_TIMEOUT_MS 1800000 In-memory sessions idle this long are ended (session-end hooks run)
SESSION_CLEANUP_INTERVAL_MS 900000 How often that sweep runs

Use Redis when you run more than about 50 concurrent conversations or several LiteBot processes. services.redis.status in /health/detail shows healthy, disabled (not connected) or unhealthy.

Hot reload

Bots and tools edited in the dashboard or through the API apply at once, without a restart. Files on disk and MongoDB edits behave as follows:

Change NODE_ENV not production NODE_ENV=production
config/bots/*.json saved, added or deleted Reloaded or unloaded Only with ENABLE_HOT_RELOAD=true
config/prompts/*.txt saved Bots using the file reload Only with ENABLE_HOT_RELOAD=true
config/tools/*.js saved Reloaded Never; restart
Tools stored in MongoDB Polled every TOOLS_DB_POLL_MS (default 15000; 0 turns polling off) Same
Bot documents edited directly in MongoDB POST /api/bots/reload (admin) or restart Restart
.env Restart with --update-env Same

Every .js file in config/tools/ is loaded as a tool, except index.js and names starting with . or template. Keep backup copies outside that folder. The admin endpoints POST /api/admin/bots/<botId>/reload and POST /api/admin/prompts/<file>.txt/reload reload one file on demand in either mode. GET /api/admin/hot-reload/status shows whether watching is on.

Capacity

Limit Default Variable
Requests per client IP on /api 500 per 5 min, or 100 per 15 min in production API_RATE_LIMIT
Voice sessions per process 10 MAX_VOICE_SESSIONS_CONCURRENT
Voice sessions per API key 50 API_KEY_DEFAULT_MAX_VOICE_CONCURRENT (key metadata overrides)
Voice sessions per logged-in user 1 MAX_VOICE_SESSIONS_PER_USER
Tool loop iterations per turn 5 REACT_MAX_ITERATIONS
LLM request timeout 30000 ms (Ollama 120000) LLM_REQUEST_TIMEOUT, <PROVIDER>_REQUEST_TIMEOUT
MongoDB connection pool 5 to 50 MONGODB_MIN_POOL_SIZE, MONGODB_MAX_POOL_SIZE

Response time is dominated by the language model and by tool webhooks, not by LiteBot's own processing. One process is one Node.js event loop. Plan memory for the knowledge-base index in Vectra mode, which lives in the process. See Cost and performance.

Backups

What Back up? Notes
MongoDB bots, tools, tenants, users, roles, api_keys Yes, always Configuration and access. tenants holds per-tenant provider keys, encrypted with a key derived from JWT_SECRET
MongoDB conversations, leads, support_tickets Yes Customer data written by chats and tools
MongoDB knowledge_documents, kb_collections Yes Knowledge-base text and collection list
MongoDB campaigns, campaign_contacts, campaign_csv_uploads, auto_dialer_settings When the auto-dialer is used
MongoDB session_analytics, request_analytics, request_traces Optional Usage, cost and per-turn traces; large
config/ Yes Bot, prompt and tool files
data/vectra/ Yes, with Vectra The vector index. Without it, re-index from knowledge_documents
.env Yes, securely Keys and JWT_SECRET. Losing JWT_SECRET makes stored tenant keys unreadable
public/, the binary Keep the previous version For rollback
mongodump --uri="$MONGODB_URI" --db=litebot --out=/backup/litebot-$(date +%F)

Safe deploy routine

The full steps are in Upgrading. The short checklist:

  1. Copy the new binary as litebot.new and the new public/ to the server; compare checksums.
  2. Wait for a quiet moment: check pm2 logs litebot for recent POST /api/chat lines and the voice session count (GET /api/voice/stats, authenticated).
  3. Back up litebot, public/ and .env with a timestamp suffix.
  4. Swap the binary and public/, then pm2 restart litebot --update-env.
  5. Check /health, /health/ready, the Loaded N bots and M tools line and the provider status.
  6. Send one test chat to a real bot, and watch the logs for ten minutes.
  7. If anything is wrong, restore the three backups and restart.

Where to go next