DataStax Official Driver
Node.js Driver
Build modern JavaScript/TypeScript applications with Cassandra!
🟢 DataStax Node.js Driver for Apache Cassandra
Official driver with modern JavaScript features - Promise-based, TypeScript support, and production-ready!
Why Use the Node.js Driver?
- 🚀 Promise-based API: Clean async/await syntax
- 📘 TypeScript Support: Full type definitions included
- ⚡ High Performance: Connection pooling, prepared statements
- 🔄 Automatic Failover: Built-in retry policies
- 📊 Load Balancing: Smart request distribution
- 🛡️ Production Ready: Battle-tested in production
Latest Version: 4.x
Supports Cassandra 2.1+ and DataStax Enterprise 4.7+
Actively maintained by DataStax with regular updates and bug fixes.
📦 Installation & Setup
1
Install the Driver
# NPM
$ npm install cassandra-driver
# Yarn
$ yarn add cassandra-driver
# With TypeScript types (already included!)
$ npm install --save-dev @types/cassandra-driver
2
Create Project Structure
# Create project
$ mkdir my-cassandra-app
$ cd my-cassandra-app
$ npm init -y
# Install driver
$ npm install cassandra-driver
# Create main file
$ touch index.js
3
Verify Installation
// index.js
const cassandra = require('cassandra-driver');
console.log('Driver version:', cassandra.version);
// Output: Driver version: 4.7.2 ✅
🔌 Connecting to Cassandra
Basic Connection
const cassandra = require('cassandra-driver');
// Create client
const client = new cassandra.Client({
contactPoints: ['127.0.0.1'],
localDataCenter: 'datacenter1',
keyspace: 'myapp'
});
// Connect
async function connect() {
await client.connect();
console.log('Connected to Cassandra!');
}
connect();
Production Configuration
const cassandra = require('cassandra-driver');
const client = new cassandra.Client({
// Cluster nodes
contactPoints: [
'10.0.0.1',
'10.0.0.2',
'10.0.0.3'
],
// Data center (REQUIRED)
localDataCenter: 'DC1',
// Keyspace
keyspace: 'production',
// Authentication
credentials: {
username: 'cassandra',
password: 'your_password'
},
// Connection pooling
pooling: {
coreConnectionsPerHost: {
[cassandra.types.distance.local]: 2,
[cassandra.types.distance.remote]: 1
}
},
// Query options
queryOptions: {
consistency: cassandra.types.consistencies.localQuorum
}
});
// Error handling
client.on('error', (err) => {
console.error('Client error:', err);
});
await client.connect();
localDataCenter is REQUIRED!
Starting with driver 4.x, you MUST specify localDataCenter.
Run nodetool status on your cluster to find the DC name.
📝 CRUD Operations
CREATE - Insert Data
// Insert user
const query = 'INSERT INTO users (id, name, email) VALUES (?, ?, ?)';
const params = ['uuid-123', 'Alice', 'alice@example.com'];
await client.execute(query, params, { prepare: true });
console.log('User inserted!');
// Insert with TTL
const queryTTL = 'INSERT INTO sessions (id, data) VALUES (?, ?) USING TTL ?';
await client.execute(queryTTL, ['session-1', 'data', 3600], { prepare: true });
READ - Query Data
// Select single user
const query = 'SELECT * FROM users WHERE id = ?';
const result = await client.execute(query, ['uuid-123'], { prepare: true });
if (result.rowLength > 0) {
const user = result.rows[0];
console.log('User:', user.name, user.email);
}
// Select multiple users
const allUsers = await client.execute('SELECT * FROM users');
allUsers.rows.forEach(user => {
console.log(user.name);
});
UPDATE - Modify Data
// Update user
const query = 'UPDATE users SET email = ? WHERE id = ?';
await client.execute(query, ['newemail@example.com', 'uuid-123'], { prepare: true });
// Update with conditions
const updateQuery = 'UPDATE users SET login_count = login_count + 1 WHERE id = ?';
await client.execute(updateQuery, ['uuid-123'], { prepare: true });
DELETE - Remove Data
// Delete user
const query = 'DELETE FROM users WHERE id = ?';
await client.execute(query, ['uuid-123'], { prepare: true });
// Delete specific columns
const deleteEmail = 'DELETE email FROM users WHERE id = ?';
await client.execute(deleteEmail, ['uuid-123'], { prepare: true });
⚡ Prepared Statements
Use prepared statements for better performance and security!
// BAD: Simple query (parsed every time)
await client.execute('SELECT * FROM users WHERE id = ?', [userId]);
// GOOD: Prepared statement (parsed once)
await client.execute(
'SELECT * FROM users WHERE id = ?',
[userId],
{ prepare: true } ← Use this!
);
// BEST: Reuse prepared statement
const query = 'INSERT INTO users (id, name) VALUES (?, ?)';
for (let i = 0; i < 1000; i++) {
await client.execute(query, [i, `User ${i}`], { prepare: true });
}
// Query prepared once, reused 1000 times! ✅
Performance Boost!
Prepared statements are 3-5x faster!
- Query parsed once on server
- Binary protocol (smaller packets)
- Protection against CQL injection
🔄 Async/Await Patterns
Basic Async/Await
async function getUser(userId) {
try {
const result = await client.execute(
'SELECT * FROM users WHERE id = ?',
[userId],
{ prepare: true }
);
if (result.rowLength === 0) {
return null;
}
return result.rows[0];
} catch (err) {
console.error('Error:', err);
throw err;
}
}
// Usage
const user = await getUser('uuid-123');
console.log(user.name);
Parallel Queries
// Execute multiple queries in parallel
async function getUserProfile(userId) {
const [user, posts, friends] = await Promise.all([
client.execute('SELECT * FROM users WHERE id = ?', [userId], { prepare: true }),
client.execute('SELECT * FROM posts WHERE user_id = ?', [userId], { prepare: true }),
client.execute('SELECT * FROM friends WHERE user_id = ?', [userId], { prepare: true })
]);
return {
user: user.rows[0],
posts: posts.rows,
friends: friends.rows
};
}
Batch Operations
// Batch insert
const queries = [
{ query: 'INSERT INTO users (id, name) VALUES (?, ?)', params: ['1', 'Alice'] },
{ query: 'INSERT INTO users (id, name) VALUES (?, ?)', params: ['2', 'Bob'] },
{ query: 'INSERT INTO users (id, name) VALUES (?, ?)', params: ['3', 'Charlie'] }
];
await client.batch(queries, { prepare: true });
console.log('Batch executed!');
🚀 Advanced Features
Stream API
Process large result sets efficiently
const query = 'SELECT * FROM users';
client.stream(query)
.on('readable', function() {
let row;
while (row = this.read()) {
console.log(row.name);
}
})
.on('end', () => {
console.log('Done!');
});
Retry Policies
Automatic retry on failures
const client = new cassandra.Client({
contactPoints: ['127.0.0.1'],
localDataCenter: 'DC1',
policies: {
retry: new cassandra
.policies.retry
.RetryPolicy()
}
});
Load Balancing
Smart request distribution
const client = new cassandra.Client({
contactPoints: ['127.0.0.1'],
localDataCenter: 'DC1',
policies: {
loadBalancing: new cassandra
.policies.loadBalancing
.DCAwareRoundRobinPolicy()
}
});
SSL/TLS
Encrypted connections
const fs = require('fs');
const client = new cassandra.Client({
contactPoints: ['127.0.0.1'],
localDataCenter: 'DC1',
sslOptions: {
ca: [fs.readFileSync('ca.pem')]
}
});
💡 Best Practices
Connection Management
- ✅ Reuse client: Create ONE client for entire app
- ✅ Connection pool: Driver manages connections automatically
- ❌ Don't create per-request: Expensive and unnecessary
- ✅ Graceful shutdown: Call
client.shutdown()on exit
Query Optimization
- ✅ Always use prepared statements:
{ prepare: true } - ✅ Use appropriate consistency: Don't always use QUORUM
- ✅ Avoid SELECT *: Query only needed columns
- ✅ Use LIMIT: Prevent large result sets
- ✅ Batch wisely: Only for same partition key
Common Mistakes
- ❌ Creating client per request → Reuse one client
- ❌ Not using prepared statements → Always use
prepare: true - ❌ Missing localDataCenter → Required in driver 4.x
- ❌ Blocking event loop → Use async/await properly
- ❌ No error handling → Always use try/catch
Complete Example
// app.js - Production-ready setup
const cassandra = require('cassandra-driver');
// Create client (ONCE for entire app)
const client = new cassandra.Client({
contactPoints: ['10.0.0.1', '10.0.0.2'],
localDataCenter: 'DC1',
keyspace: 'myapp',
credentials: {
username: process.env.CASSANDRA_USER,
password: process.env.CASSANDRA_PASSWORD
},
queryOptions: {
consistency: cassandra.types.consistencies.localQuorum
}
});
// Connect on startup
async function init() {
try {
await client.connect();
console.log('Connected to Cassandra!');
} catch (err) {
console.error('Connection failed:', err);
process.exit(1);
}
}
// User operations
class UserRepository {
async create(id, name, email) {
const query = 'INSERT INTO users (id, name, email) VALUES (?, ?, ?)';
await client.execute(query, [id, name, email], { prepare: true });
}
async findById(id) {
const query = 'SELECT * FROM users WHERE id = ?';
const result = await client.execute(query, [id], { prepare: true });
return result.rowLength > 0 ? result.rows[0] : null;
}
async update(id, email) {
const query = 'UPDATE users SET email = ? WHERE id = ?';
await client.execute(query, [email, id], { prepare: true });
}
async delete(id) {
const query = 'DELETE FROM users WHERE id = ?';
await client.execute(query, [id], { prepare: true });
}
}
// Graceful shutdown
process.on('SIGTERM', async () => {
await client.shutdown();
process.exit(0);
});
// Export
module.exports = { client, UserRepository };
🎉 You're Ready to Build with Node.js!
You now know how to use the Node.js driver for Cassandra!
🚀 Quick Start Checklist:
- ✅ Install:
npm install cassandra-driver - ✅ Create client with
localDataCenter - ✅ Always use
{ prepare: true } - ✅ Use async/await for clean code
- ✅ Implement proper error handling
- ✅ Reuse ONE client for entire app
- ✅ Graceful shutdown on exit
💡 Key Takeaways:
- 🟢 Modern API: Promise-based with async/await
- 📘 TypeScript: Full type definitions included
- ⚡ Performance: Prepared statements are 3-5x faster
- 🔄 Automatic: Retry, failover, load balancing built-in
- 🛡️ Production Ready: Battle-tested at scale
🟢 Build amazing apps with Node.js + Cassandra! 🚀
Advertisement
📱 Responsive Ad 📱