Skip to main content

Database Setup

Complete guide for setting up and managing the SBM CRM Platform database.

Database Requirements​

  • PostgreSQL: Version 13 or later
  • Storage: Minimum 50GB (varies by data volume)
  • Backup Storage: 2x database size recommended

Initial Setup​

Create Database​

# Connect as postgres user
sudo -u postgres psql

# Create database
CREATE DATABASE sbmcrm_production;

# Create user
CREATE USER sbmcrm WITH PASSWORD 'your_secure_password';

# Grant privileges
GRANT ALL PRIVILEGES ON DATABASE sbmcrm_production TO sbmcrm;

# Connect to database
\c sbmcrm_production

# Grant schema privileges
GRANT ALL ON SCHEMA public TO sbmcrm;

# Exit
\q

Run Migrations​

# Run all migrations
npm run migrate:production

# Or using Docker
docker-compose exec api npm run migrate

Database Schema​

Core Tables​

  • customers - Customer profiles
  • points_transactions - Points earned/redeemed
  • rewards - Reward catalog
  • campaigns - Marketing campaigns
  • segments - Customer segments
  • notifications - Notification history
  • bookings - Booking records

Indexes​

Key indexes are created automatically:

-- Customer indexes
CREATE INDEX idx_customers_email ON customers(email);
CREATE INDEX idx_customers_tier ON customers(tier);
CREATE INDEX idx_customers_created_at ON customers(created_at);

-- Points transactions
CREATE INDEX idx_points_customer_id ON points_transactions(customer_id);
CREATE INDEX idx_points_created_at ON points_transactions(created_at);
CREATE INDEX idx_points_type ON points_transactions(type);

-- Campaign participants
CREATE INDEX idx_campaign_participants_campaign ON campaign_participants(campaign_id);
CREATE INDEX idx_campaign_participants_customer ON campaign_participants(customer_id);

Database Maintenance​

Vacuum and Analyze​

Regular maintenance to optimize performance:

-- Vacuum database
VACUUM ANALYZE;

-- Vacuum specific table
VACUUM ANALYZE customers;

-- Full vacuum (requires exclusive lock)
VACUUM FULL;

Check Database Size​

SELECT 
pg_database.datname,
pg_size_pretty(pg_database_size(pg_database.datname)) AS size
FROM pg_database
WHERE datname = 'sbmcrm_production';

Check 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;

Performance Tuning​

PostgreSQL Configuration​

Edit /etc/postgresql/13/main/postgresql.conf:

# Memory settings
shared_buffers = 4GB
effective_cache_size = 12GB
work_mem = 64MB
maintenance_work_mem = 1GB

# Connection settings
max_connections = 200
max_worker_processes = 8

# Query planner
random_page_cost = 1.1
effective_io_concurrency = 200

# WAL settings
wal_buffers = 16MB
checkpoint_completion_target = 0.9

Connection Pooling​

Use PgBouncer for connection pooling:

[databases]
sbmcrm_production = host=localhost port=5432 dbname=sbmcrm_production

[pgbouncer]
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 25

Backup and Restore​

Automated Backups​

Set up cron job for daily backups:

# Add to crontab
0 2 * * * /usr/local/bin/backup-sbmcrm-db.sh

Backup script:

#!/bin/bash
BACKUP_DIR="/backups/sbmcrm"
DATE=$(date +%Y%m%d_%H%M%S)
pg_dump -U sbmcrm -h localhost sbmcrm_production | gzip > "$BACKUP_DIR/sbmcrm_$DATE.sql.gz"

# Keep only last 30 days
find $BACKUP_DIR -name "sbmcrm_*.sql.gz" -mtime +30 -delete

Manual Backup​

# Full backup
pg_dump -U sbmcrm -h localhost sbmcrm_production > backup.sql

# Compressed backup
pg_dump -U sbmcrm -h localhost sbmcrm_production | gzip > backup.sql.gz

# Backup specific table
pg_dump -U sbmcrm -h localhost -t customers sbmcrm_production > customers_backup.sql

Restore​

# Restore from backup
psql -U sbmcrm -h localhost sbmcrm_production < backup.sql

# Restore from compressed backup
gunzip < backup.sql.gz | psql -U sbmcrm -h localhost sbmcrm_production

Replication​

Set Up Read Replica​

  1. Configure primary server
  2. Set up streaming replication
  3. Configure replica server
  4. Start replication

See PostgreSQL documentation for detailed replication setup.

Monitoring​

Check Active Connections​

SELECT 
count(*) as total_connections,
state,
wait_event_type
FROM pg_stat_activity
WHERE datname = 'sbmcrm_production'
GROUP BY state, wait_event_type;

Check Slow Queries​

SELECT 
query,
calls,
total_time,
mean_time,
max_time
FROM pg_stat_statements
WHERE query NOT LIKE '%pg_stat%'
ORDER BY mean_time DESC
LIMIT 10;

Check Database Locks​

SELECT 
locktype,
relation::regclass,
mode,
granted
FROM pg_locks
WHERE relation IS NOT NULL;

Troubleshooting​

Connection Issues​

# Check PostgreSQL is running
sudo systemctl status postgresql

# Check connection
psql -U sbmcrm -h localhost -d sbmcrm_production

# Check PostgreSQL logs
sudo tail -f /var/log/postgresql/postgresql-*.log

Performance Issues​

  1. Check for long-running queries
  2. Analyze query execution plans
  3. Review index usage
  4. Check for table bloat
  5. Monitor connection pool usage

Disk Space​

-- Check database size
SELECT pg_size_pretty(pg_database_size('sbmcrm_production'));

-- Check available disk space
SELECT pg_size_pretty(
pg_database_size('sbmcrm_production') -
(SELECT setting::bigint FROM pg_settings WHERE name = 'data_directory')
);