Skip to content

Configuration

ScyllinX provides flexible configuration options to connect to various databases including ScyllaDB, PostgreSQL, MySQL, and SQLite. This guide covers all configuration aspects from basic setup to advanced options.

Database Configuration

Configuration Structure

ScyllinX uses a centralized configuration object that defines connections, default settings, and database-specific options:

typescript
// src/config/database.ts
import { DatabaseConfig } from 'scyllinx';

export const databaseConfig: DatabaseConfig = {
  // Default connection name
  default: 'scylladb',
  
  // Connection definitions
  connections: {
    scylladb: {
      driver: 'scylladb',
      contactPoints: ['127.0.0.1'],
      localDataCenter: 'datacenter1',
      keyspace: 'my_app',
      credentials: {
        username: 'cassandra',
        password: 'cassandra'
      }
    },
    
    postgres: {
      driver: 'postgres',
      host: 'localhost',
      port: 5432,
      database: 'my_app',
      username: 'postgres',
      password: 'password'
    }
  }
};

ScyllaDB Configuration

Basic ScyllaDB Setup

typescript
const scyllaConfig = {
  driver: 'scylladb',
  contactPoints: ['127.0.0.1', '127.0.0.2', '127.0.0.3'],
  localDataCenter: 'datacenter1',
  keyspace: 'my_keyspace',
  credentials: {
    username: 'cassandra',
    password: 'cassandra'
  }
};

Advanced ScyllaDB Options

typescript
const advancedScyllaConfig = {
  driver: 'scylladb',
  contactPoints: ['node1.scylla.com', 'node2.scylla.com'],
  localDataCenter: 'us-east-1',
  keyspace: 'production_app',
  
  // Authentication
  credentials: {
    username: process.env.SCYLLA_USERNAME,
    password: process.env.SCYLLA_PASSWORD
  },
  
  // Connection pooling
  pooling: {
    coreConnectionsPerHost: {
      [distance.local]: 2,
      [distance.remote]: 1
    },
    maxConnectionsPerHost: {
      [distance.local]: 8,
      [distance.remote]: 2
    }
  },
  
  // Socket options
  socketOptions: {
    connectTimeout: 30000,
    readTimeout: 30000,
    keepAlive: true,
    keepAliveDelay: 0,
    tcpNoDelay: true
  },
  
  // SSL/TLS configuration
  sslOptions: {
    rejectUnauthorized: true,
    cert: fs.readFileSync('/path/to/client-cert.pem'),
    key: fs.readFileSync('/path/to/client-key.pem'),
    ca: [fs.readFileSync('/path/to/ca-cert.pem')]
  },
  
  // Query options
  queryOptions: {
    consistency: consistency.localQuorum,
    serialConsistency: consistency.localSerial,
    fetchSize: 5000,
    autoPage: true,
    prepare: true
  },
  
  // Retry policy
  policies: {
    retry: new RetryPolicy(),
    loadBalancing: new DCAwareRoundRobinPolicy('datacenter1'),
    reconnection: new ExponentialReconnectionPolicy(1000, 10 * 60 * 1000)
  },
  
  // Metrics
  metrics: {
    enabled: true,
    buckets: [1, 5, 15, 50, 100, 200, 500, 1000, 2000]
  }
};

ScyllaDB Cloud Configuration

typescript
const scyllaCloudConfig = {
  driver: 'scylladb',
  cloud: {
    secureConnectBundle: '/path/to/secure-connect-bundle.zip'
  },
  credentials: {
    username: 'scylla',
    password: 'your-password'
  },
  keyspace: 'your_keyspace'
};

SQL Database Configuration

PostgreSQL

typescript
const postgresConfig = {
  driver: 'postgres',
  host: 'localhost',
  port: 5432,
  database: 'my_app',
  username: 'postgres',
  password: 'password',
  
  // Connection pool settings
  pool: {
    min: 2,
    max: 10,
    acquireTimeoutMillis: 30000,
    createTimeoutMillis: 30000,
    destroyTimeoutMillis: 5000,
    idleTimeoutMillis: 30000,
    reapIntervalMillis: 1000,
    createRetryIntervalMillis: 200
  },
  
  // SSL configuration
  ssl: {
    rejectUnauthorized: false,
    ca: fs.readFileSync('/path/to/ca-certificate.crt').toString(),
    key: fs.readFileSync('/path/to/client-key.key').toString(),
    cert: fs.readFileSync('/path/to/client-certificate.crt').toString()
  },
  
  // Additional options
  options: {
    timezone: 'UTC',
    charset: 'utf8mb4',
    collate: 'utf8mb4_unicode_ci'
  }
};

MySQL

typescript
const mysqlConfig = {
  driver: 'mysql',
  host: 'localhost',
  port: 3306,
  database: 'my_app',
  username: 'root',
  password: 'password',
  
  // MySQL specific options
  options: {
    charset: 'utf8mb4',
    collate: 'utf8mb4_unicode_ci',
    timezone: '+00:00',
    typeCast: true,
    supportBigNumbers: true,
    bigNumberStrings: true,
    dateStrings: false,
    debug: false,
    trace: true,
    multipleStatements: false,
    flags: '',
    ssl: {
      ca: fs.readFileSync('/path/to/ca.pem'),
      cert: fs.readFileSync('/path/to/client-cert.pem'),
      key: fs.readFileSync('/path/to/client-key.pem')
    }
  }
};

SQLite

typescript
const sqliteConfig = {
  driver: 'sqlite',
  filename: './database.sqlite',
  
  // SQLite options
  options: {
    verbose: console.log,
    fileMustExist: false,
    timeout: 5000,
    readonly: false
  }
};

Environment-Based Configuration

Using Environment Variables

typescript
// src/config/database.ts
export const databaseConfig = {
  default: process.env.DB_CONNECTION || 'scylladb',
  
  connections: {
    scylladb: {
      driver: 'scylladb',
      contactPoints: process.env.SCYLLA_CONTACT_POINTS?.split(',') || ['127.0.0.1'],
      localDataCenter: process.env.SCYLLA_DATACENTER || 'datacenter1',
      keyspace: process.env.SCYLLA_KEYSPACE || 'my_app',
      credentials: {
        username: process.env.SCYLLA_USERNAME || 'cassandra',
        password: process.env.SCYLLA_PASSWORD || 'cassandra'
      }
    },
    
    postgres: {
      driver: 'postgres',
      host: process.env.DB_HOST || 'localhost',
      port: parseInt(process.env.DB_PORT || '5432'),
      database: process.env.DB_DATABASE || 'my_app',
      username: process.env.DB_USERNAME || 'postgres',
      password: process.env.DB_PASSWORD || 'password'
    }
  }
};

Environment Files

Create different environment files for different stages:

bash
# .env.development
DB_CONNECTION=scylladb
SCYLLA_CONTACT_POINTS=127.0.0.1
SCYLLA_DATACENTER=datacenter1
SCYLLA_KEYSPACE=my_app_dev
SCYLLA_USERNAME=cassandra
SCYLLA_PASSWORD=cassandra

# .env.production
DB_CONNECTION=scylladb
SCYLLA_CONTACT_POINTS=node1.prod.com,node2.prod.com,node3.prod.com
SCYLLA_DATACENTER=us-east-1
SCYLLA_KEYSPACE=my_app_prod
SCYLLA_USERNAME=prod_user
SCYLLA_PASSWORD=secure_password

# .env.test
DB_CONNECTION=sqlite
DB_FILENAME=:memory:

Loading Environment Configuration

typescript
// src/config/index.ts
import dotenv from 'dotenv';
import path from 'path';

// Load environment-specific config
const env = process.env.NODE_ENV || 'development';
dotenv.config({ path: path.resolve(process.cwd(), `.env.${env}`) });

// Fallback to default .env
dotenv.config();

export { databaseConfig } from './database';

Multiple Database Connections

Defining Multiple Connections

typescript
export const databaseConfig = {
  default: 'primary',
  
  connections: {
    // Primary ScyllaDB connection
    primary: {
      driver: 'scylladb',
      contactPoints: ['scylla1.com', 'scylla2.com'],
      localDataCenter: 'datacenter1',
      keyspace: 'main_app'
    },
    
    // Analytics ScyllaDB connection
    analytics: {
      driver: 'scylladb',
      contactPoints: ['analytics1.com', 'analytics2.com'],
      localDataCenter: 'datacenter2',
      keyspace: 'analytics'
    },
    
    // PostgreSQL for relational data
    postgres: {
      driver: 'postgres',
      host: 'postgres.com',
      database: 'relational_data'
    },
    
    // Redis for caching
    redis: {
      driver: 'redis',
      host: 'redis.com',
      port: 6379
    }
  }
};

Using Different Connections in Models

typescript
// Primary database model
class User extends Model<UserAttributes> {
  protected static connection = 'primary';
  protected static table = 'users';
}

// Analytics database model
class UserEvent extends Model<UserEventAttributes> {
  protected static connection = 'analytics';
  protected static table = 'user_events';
}

// PostgreSQL model
class Report extends Model<ReportAttributes> {
  protected static connection = 'postgres';
  protected static table = 'reports';
}

Connection Management

Manual Connection Management

typescript
import { ConnectionManager } from 'scyllinx';

const connectionManager = ConnectionManager.getInstance();

// Initialize all connections
await connectionManager.initialize(databaseConfig);

// Get specific connection
const scyllaConnection = connectionManager.getConnection('scylladb');
const postgresConnection = connectionManager.getConnection('postgres');

// Test connections
const isScyllaHealthy = await connectionManager.testConnection('scylladb');
const isPostgresHealthy = await connectionManager.testConnection('postgres');

// Close connections
await scyllaConnection.disconnect();
await connectionManager.disconnectAll();

Connection Health Monitoring

typescript
class DatabaseHealthMonitor {
  private connectionManager: ConnectionManager;
  
  constructor() {
    this.connectionManager = ConnectionManager.getInstance();
  }
  
  async checkAllConnections(): Promise<Record<string, boolean>> {
    const connections = this.connectionManager.getConnectionNames();
    const results: Record<string, boolean> = {};
    
    for (const connectionName of connections) {
      try {
        results[connectionName] = await this.connectionManager.testConnection(connectionName);
      } catch (error) {
        console.error(`Connection ${connectionName} failed:`, error);
        results[connectionName] = false;
      }
    }
    
    return results;
  }
}

Performance Configuration

Connection Pooling

typescript
export const databaseConfig = {
  connections: {
    postgres: {
      driver: 'postgres',
      // ... connection details
      
      pool: {
        // Minimum connections in pool
        min: 2,
        
        // Maximum connections in pool
        max: 10,
        
        // Acquire timeout
        acquireTimeoutMillis: 30000,
        
        // Create timeout
        createTimeoutMillis: 30000,
        
        // Destroy timeout
        destroyTimeoutMillis: 5000,
        
        // Idle timeout
        idleTimeoutMillis: 30000,
        
        // Reap interval
        reapIntervalMillis: 1000,
        
        // Create retry interval
        createRetryIntervalMillis: 200,
        
        // Validation query
        validationQuery: 'SELECT 1'
      }
    }
  }
};

Query Optimization

typescript
export const databaseConfig = {
  // ... other config
  
  queryOptions: {
    // Default fetch size for ScyllaDB
    fetchSize: 5000,
    
    // Enable auto-paging
    autoPage: true,
    
    // Prepare statements by default
    prepare: true,
    
    // Default consistency level
    consistency: 'localQuorum',
    
    // Query timeout
    timeout: 30000
  }
};

Security Configuration

SSL/TLS Configuration

typescript
import fs from 'fs';

export const databaseConfig = {
  connections: {
    secure_scylla: {
      driver: 'scylladb',
      contactPoints: ['secure-node1.com', 'secure-node2.com'],
      
      sslOptions: {
        // Reject unauthorized certificates
        rejectUnauthorized: true,
        
        // Client certificate
        cert: fs.readFileSync('/path/to/client-cert.pem'),
        
        // Client private key
        key: fs.readFileSync('/path/to/client-key.pem'),
        
        // Certificate Authority
        ca: [fs.readFileSync('/path/to/ca-cert.pem')],
        
        // Server name for SNI
        servername: 'scylla.example.com',
        
        // Cipher suites
        ciphers: 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384',
        
        // Protocol version
        secureProtocol: 'TLSv1_2_method'
      }
    }
  }
};

Authentication Configuration

typescript
export const databaseConfig = {
  connections: {
    scylladb: {
      driver: 'scylladb',
      
      // Username/password authentication
      credentials: {
        username: process.env.SCYLLA_USERNAME,
        password: process.env.SCYLLA_PASSWORD
      },
      
      // Or use authentication provider
      authProvider: new PlainTextAuthProvider(
        process.env.SCYLLA_USERNAME!,
        process.env.SCYLLA_PASSWORD!
      )
    }
  }
};

Testing Configuration

Test Database Configuration

typescript
// src/config/database.test.ts
export const testDatabaseConfig = {
  default: 'test',
  
  connections: {
    test: {
      driver: 'sqlite',
      filename: ':memory:', // In-memory database for tests
      
      options: {
        verbose: false // Disable logging in tests
      }
    },
    
    test_scylla: {
      driver: 'scylladb',
      contactPoints: ['127.0.0.1'],
      keyspace: 'test_keyspace',
      
      // Use different keyspace for tests
      testKeyspace: true
    }
  },
};

Environment-Specific Test Config

typescript
// jest.config.js
module.exports = {
  setupFilesAfterEnv: ['<rootDir>/src/test/setup.ts'],
  testEnvironment: 'node'
};

// src/test/setup.ts
import { ConnectionManager } from 'scyllinx';
import { testDatabaseConfig } from '../config/database.test';

beforeAll(async () => {
  const connectionManager = ConnectionManager.getInstance();
  await connectionManager.initialize(testDatabaseConfig);
});

afterAll(async () => {
  const connectionManager = ConnectionManager.getInstance();
  await connectionManager.closeAllConnections();
});

Best Practices

1. Use Environment Variables

Always use environment variables for sensitive information:

typescript
// ✅ Good
credentials: {
  username: process.env.SCYLLA_USERNAME,
  password: process.env.SCYLLA_PASSWORD
}

// ❌ Bad
credentials: {
  username: 'cassandra',
  password: 'password123'
}

2. Separate Configurations by Environment

typescript
// src/config/environments/development.ts
export const developmentConfig = {
  // Development-specific settings
};

// src/config/environments/production.ts
export const productionConfig = {
  // Production-specific settings
};

// src/config/index.ts
const env = process.env.NODE_ENV || 'development';
export const config = require(`./environments/${env}`).default;

3. Use Connection Pooling

Always configure appropriate connection pooling:

typescript
pool: {
  min: 2,
  max: 10,
  acquireTimeoutMillis: 30000,
  idleTimeoutMillis: 30000
}

4. Enable SSL in Production

typescript
const isProduction = process.env.NODE_ENV === 'production';

sslOptions: isProduction ? {
  rejectUnauthorized: true,
  ca: fs.readFileSync('/path/to/ca-cert.pem')
} : undefined

5. Configure Appropriate Timeouts

typescript
socketOptions: {
  connectTimeout: 30000,
  readTimeout: 30000
},
queryOptions: {
  timeout: 30000
}

This comprehensive configuration guide covers all aspects of setting up ScyllinX for different environments and use cases. Proper configuration is crucial for optimal performance, security, and reliability of your database operations.

Released under the MIT License.