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.