Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Merkurcode/nauto-console/llms.txt

Use this file to discover all available pages before exploring further.

Chatwoot uses PostgreSQL as its primary database. This guide covers all PostgreSQL configuration options and best practices for self-hosted installations.

Database Connection Configuration

POSTGRES_HOST
string
required
PostgreSQL server hostname or IP address.Examples:
  • localhost - Local installation
  • postgres - Docker Compose service name
  • db.example.com - Remote database server
  • 10.0.1.5 - IP address
Default: localhost
POSTGRES_PORT
number
PostgreSQL server port.Default: 5432
POSTGRES_DATABASE
string
Name of the PostgreSQL database.Defaults by environment:
  • Development: chatwoot_dev
  • Test: chatwoot_test
  • Production: chatwoot_production
Note: Leave empty to use environment-specific defaults.
POSTGRES_USERNAME
string
required
PostgreSQL user for authentication.Defaults by environment:
  • Development: postgres
  • Test: postgres
  • Production: chatwoot_prod
POSTGRES_PASSWORD
string
required
Password for PostgreSQL user authentication.Security: Use a strong, unique password for production environments.

Performance Configuration

RAILS_MAX_THREADS
number
Maximum number of threads for Rails application.This directly affects the database connection pool size for web processes.Default: 5Formula: Database pool size = RAILS_MAX_THREADS for web processes
SIDEKIQ_CONCURRENCY
number
Number of concurrent Sidekiq worker threads.This affects the database connection pool size for Sidekiq processes.Default: 10Formula: Database pool size = SIDEKIQ_CONCURRENCY for Sidekiq processes
DB_POOL_REAPING_FREQUENCY
number
Frequency in seconds to run the connection pool reaper.The reaper attempts to find and recover connections from dead threads, preventing connection leaks.Default: 30Range: 10-60 seconds recommended
POSTGRES_STATEMENT_TIMEOUT
string
Maximum time a database query can run before being terminated.Default: 14sFormat: Number followed by time unit (ms, s, min)Examples:
  • 14s - 14 seconds
  • 30s - 30 seconds
  • 1min - 1 minute
Note: This value is set close to the Rack timeout value. Only modify when required.

Connection Pool Sizing

Chatwoot automatically adjusts the database connection pool based on the process type: Web processes:
pool_size = ENV.fetch('RAILS_MAX_THREADS', 5)
Sidekiq processes:
pool_size = ENV.fetch('SIDEKIQ_CONCURRENCY', 10)

Calculating Total Connections

Total database connections required:
Total = (Web workers × RAILS_MAX_THREADS) + (Sidekiq processes × SIDEKIQ_CONCURRENCY) + buffer
Example calculation:
  • 4 web workers with RAILS_MAX_THREADS=5: 20 connections
  • 2 Sidekiq processes with SIDEKIQ_CONCURRENCY=10: 20 connections
  • Buffer for migrations, console, etc.: 10 connections
  • Total required: 50 connections

PostgreSQL Version Requirements

Minimum version: PostgreSQL 12
Recommended version: PostgreSQL 14 or higher
Chatwoot uses modern PostgreSQL features including:
  • JSONB columns
  • Full-text search
  • Partitioning
  • Generated columns

Configuration Examples

Local Development

POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DATABASE=chatwoot_dev
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=postgres
RAILS_MAX_THREADS=5

Docker Compose

POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DATABASE=chatwoot
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=secure_password_here
RAILS_MAX_THREADS=5

Production Deployment

POSTGRES_HOST=db.example.com
POSTGRES_PORT=5432
POSTGRES_DATABASE=chatwoot_production
POSTGRES_USERNAME=chatwoot_user
POSTGRES_PASSWORD=very_secure_password_here
RAILS_MAX_THREADS=5
POSTGRES_STATEMENT_TIMEOUT=14s
DB_POOL_REAPING_FREQUENCY=30

High-Traffic Production

POSTGRES_HOST=db.example.com
POSTGRES_PORT=5432
POSTGRES_DATABASE=chatwoot_production
POSTGRES_USERNAME=chatwoot_user
POSTGRES_PASSWORD=very_secure_password_here
RAILS_MAX_THREADS=10
SIDEKIQ_CONCURRENCY=20
POSTGRES_STATEMENT_TIMEOUT=30s
DB_POOL_REAPING_FREQUENCY=15

Database Setup

Creating the Database

For a new installation:
# Create database
rails db:create

# Run migrations
rails db:migrate

# Seed initial data (optional)
rails db:seed

Database User Setup

Create a dedicated PostgreSQL user for Chatwoot:
-- Connect as postgres superuser
CREATE USER chatwoot_user WITH PASSWORD 'secure_password';
CREATE DATABASE chatwoot_production OWNER chatwoot_user;
GRANT ALL PRIVILEGES ON DATABASE chatwoot_production TO chatwoot_user;

PostgreSQL Server Configuration

Recommended PostgreSQL server settings for production:

postgresql.conf

# Connection Settings
max_connections = 100
shared_buffers = 256MB

# Query Performance
effective_cache_size = 1GB
random_page_cost = 1.1

# Write Performance
wal_buffers = 16MB
checkpoint_completion_target = 0.9

# Logging
log_statement = 'mod'  # Log data-modifying queries
log_duration = off
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '

# Timeouts
statement_timeout = 30000  # 30 seconds

pg_hba.conf

# Allow Chatwoot app servers to connect
host    chatwoot_production    chatwoot_user    10.0.1.0/24    scram-sha-256

# Local connections
local   all                    all                             peer
host    all                    all              127.0.0.1/32   scram-sha-256

Managed PostgreSQL Services

AWS RDS PostgreSQL

POSTGRES_HOST=your-instance.123456.us-east-1.rds.amazonaws.com
POSTGRES_PORT=5432
POSTGRES_DATABASE=chatwoot_production
POSTGRES_USERNAME=chatwoot_admin
POSTGRES_PASSWORD=your_secure_password
Recommendations:
  • Use db.t3.medium or larger for production
  • Enable automated backups
  • Use Multi-AZ for high availability
  • Enable Performance Insights

Google Cloud SQL PostgreSQL

POSTGRES_HOST=/cloudsql/project:region:instance
POSTGRES_PORT=5432
POSTGRES_DATABASE=chatwoot_production
POSTGRES_USERNAME=chatwoot_user
POSTGRES_PASSWORD=your_secure_password
For Cloud Run or App Engine: Use Unix socket connection with the Cloud SQL Proxy.

Azure Database for PostgreSQL

POSTGRES_HOST=your-server.postgres.database.azure.com
POSTGRES_PORT=5432
POSTGRES_DATABASE=chatwoot_production
POSTGRES_USERNAME=chatwoot_user@your-server
POSTGRES_PASSWORD=your_secure_password
Note: Azure requires the server name suffix in the username.

DigitalOcean Managed Database

POSTGRES_HOST=your-cluster.db.ondigitalocean.com
POSTGRES_PORT=25060
POSTGRES_DATABASE=chatwoot_production
POSTGRES_USERNAME=doadmin
POSTGRES_PASSWORD=your_secure_password
Note: DigitalOcean uses custom ports and provides a connection string.

Heroku Postgres

# Heroku automatically sets DATABASE_URL
# No manual configuration needed
Heroku provides DATABASE_URL which Chatwoot automatically uses.

Backup and Restore

Manual Backup

# Create backup
pg_dump -h localhost -U postgres -Fc chatwoot_production > backup.dump

# Create SQL backup
pg_dump -h localhost -U postgres chatwoot_production > backup.sql

Restore from Backup

# Restore from custom format
pg_restore -h localhost -U postgres -d chatwoot_production backup.dump

# Restore from SQL
psql -h localhost -U postgres -d chatwoot_production < backup.sql

Automated Backups

Set up automated backups using cron:
#!/bin/bash
# backup.sh

BACKUP_DIR="/var/backups/chatwoot"
DATE=$(date +%Y%m%d_%H%M%S)
FILENAME="chatwoot_${DATE}.dump"

pg_dump -h localhost -U postgres -Fc chatwoot_production > "${BACKUP_DIR}/${FILENAME}"

# Keep only last 7 days of backups
find ${BACKUP_DIR} -name "chatwoot_*.dump" -mtime +7 -delete
Cron entry:
0 2 * * * /path/to/backup.sh

Database Maintenance

Vacuum and Analyze

Regular maintenance improves query performance:
-- Vacuum all tables
VACUUM ANALYZE;

-- Vacuum specific table
VACUUM ANALYZE conversations;

-- Full vacuum (locks table)
VACUUM FULL ANALYZE conversations;
Automate with cron:
# Weekly vacuum
0 3 * * 0 psql -h localhost -U postgres -d chatwoot_production -c "VACUUM ANALYZE;"

Reindex

Rebuild indexes periodically:
-- Reindex database
REINDEX DATABASE chatwoot_production;

-- Reindex specific table
REINDEX TABLE conversations;

Monitoring

Key Metrics to Monitor

  1. Connection count
    SELECT count(*) FROM pg_stat_activity;
    
  2. Long-running queries
    SELECT pid, now() - query_start AS duration, query
    FROM pg_stat_activity
    WHERE state = 'active'
    AND now() - query_start > interval '10 seconds';
    
  3. Database size
    SELECT pg_size_pretty(pg_database_size('chatwoot_production'));
    
  4. Table sizes
    SELECT schemaname, tablename,
           pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
    FROM pg_tables
    WHERE schemaname = 'public'
    ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
    LIMIT 10;
    
  5. Cache hit ratio
    SELECT 
      sum(heap_blks_read) as heap_read,
      sum(heap_blks_hit)  as heap_hit,
      sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) as ratio
    FROM pg_statio_user_tables;
    

Troubleshooting

Connection refused

Symptoms: could not connect to server: Connection refused Solutions:
  • Verify PostgreSQL is running: systemctl status postgresql
  • Check PostgreSQL is listening: ss -tlnp | grep 5432
  • Verify POSTGRES_HOST and POSTGRES_PORT are correct
  • Check firewall rules allow connections

Authentication failed

Symptoms: FATAL: password authentication failed for user Solutions:
  • Verify username and password are correct
  • Check pg_hba.conf allows connection from your IP
  • Ensure authentication method matches (md5, scram-sha-256)
  • Reload PostgreSQL after config changes: systemctl reload postgresql

Too many connections

Symptoms: FATAL: sorry, too many clients already Solutions:
  • Increase max_connections in postgresql.conf
  • Reduce connection pool sizes in application
  • Check for connection leaks
  • Implement connection pooling with PgBouncer

Slow queries

Symptoms: Requests timeout, POSTGRES_STATEMENT_TIMEOUT errors Solutions:
  • Identify slow queries in PostgreSQL logs
  • Add missing indexes: rails db:migrate
  • Run VACUUM ANALYZE to update statistics
  • Increase POSTGRES_STATEMENT_TIMEOUT if needed
  • Consider read replicas for heavy SELECT queries

Disk space issues

Symptoms: ERROR: could not extend file Solutions:
  • Check disk space: df -h
  • Run VACUUM FULL to reclaim space
  • Archive old data
  • Increase disk size

Migration failures

Symptoms: rails db:migrate fails Solutions:
  • Check PostgreSQL logs for detailed errors
  • Ensure database user has required permissions
  • Verify PostgreSQL version meets requirements
  • Check for conflicting data before migration

Security Best Practices

  1. Use strong passwords: Generate complex passwords for database users
  2. Limit connections: Configure pg_hba.conf to allow only necessary IPs
  3. SSL/TLS: Enable SSL for database connections in production
  4. Least privilege: Grant only required permissions to application user
  5. Regular updates: Keep PostgreSQL updated with security patches
  6. Audit logs: Enable query logging for security monitoring
  7. Network isolation: Run database in private network, not exposed to internet

Performance Optimization

Connection Pooling with PgBouncer

For high-traffic deployments, use PgBouncer:
# pgbouncer.ini
[databases]
chatwoot_production = host=localhost dbname=chatwoot_production

[pgbouncer]
pool_mode = transaction
max_client_conn = 100
default_pool_size = 20
Update Chatwoot configuration:
POSTGRES_HOST=localhost
POSTGRES_PORT=6432  # PgBouncer port

Read Replicas

For read-heavy workloads, configure read replicas and use Rails multiple databases feature.

Build docs developers (and LLMs) love