-
-
Notifications
You must be signed in to change notification settings - Fork 0
Database Integration
Master database performance testing - Learn to benchmark SQLite, Redis, and cloud storage integrations with real-world examples and optimization techniques.
This tutorial covers:
- SQLite performance testing and optimization
- Redis integration and caching patterns
- Cloud storage benchmarking (S3-compatible)
- Database connection pooling
- Query optimization techniques
- Migration testing strategies
- Arsenal Lab installed (Getting Started)
- Basic SQL knowledge
- Understanding of database concepts
- 15-20 minutes available
cd Arsenal-Lab
bun run devNavigate to http://localhost:3655 and select "Database Infrastructure Arsenal".
- SQLite Demo: In-memory database testing
- Redis Demo: Cache performance testing
- Performance Metrics: Real-time database stats
- Code Examples: Copy-paste ready snippets
- Click "SQLite Demo"
- Click "Create Test Database"
- Run "Basic CRUD Operations"
What you'll see:
β
Connected to SQLite database
β
Created users table
β
Inserted 100 test records
β
Query executed in 45ms
β
Retrieved 100 records
- Connection time: How fast SQLite initializes
- Query execution: Time to run SELECT/INSERT/UPDATE/DELETE
- Memory usage: RAM consumption for in-memory databases
- Transaction speed: Bulk operation performance
-- Test different batch sizes
INSERT INTO users (name, email, created_at) VALUES
('User 1', 'user1@example.com', datetime('now')),
('User 2', 'user2@example.com', datetime('now')),
-- ... up to 1000 recordsPerformance insights:
- Transaction grouping reduces overhead
- Prepared statements improve performance
- Indexes speed up SELECT queries
-- Test indexed vs non-indexed queries
CREATE INDEX idx_users_email ON users(email);
-- Benchmark these queries:
SELECT * FROM users WHERE email = 'test@example.com'; -- Uses index
SELECT * FROM users WHERE name LIKE '%test%'; -- No index- Switch to "Redis Demo" tab
- Click "Connect to Redis"
- Test basic "SET/GET Operations"
Expected output:
β
Connected to Redis server
β
SET operation: 1.2ms
β
GET operation: 0.8ms
β
Pipeline operations: 2.8ms for 10 commands
// Basic key-value operations
await redis.set('user:123:name', 'John Doe');
await redis.set('user:123:email', 'john@example.com');
const name = await redis.get('user:123:name');// Store structured data
await redis.hset('user:123', {
name: 'John Doe',
email: 'john@example.com',
age: 30,
active: true
});
const user = await redis.hgetall('user:123');// Leaderboards and ranking
await redis.zadd('leaderboard', [
{ score: 1500, member: 'player1' },
{ score: 1200, member: 'player2' },
{ score: 1800, member: 'player3' }
]);
const topPlayers = await redis.zrevrange('leaderboard', 0, 2, 'WITHSCORES');class RedisCache {
constructor(redis) {
this.redis = redis;
this.ttl = 3600; // 1 hour
}
async get(key) {
const cached = await this.redis.get(key);
if (cached) {
return JSON.parse(cached);
}
return null;
}
async set(key, value, ttl = this.ttl) {
await this.redis.setex(key, ttl, JSON.stringify(value));
}
async invalidate(pattern) {
const keys = await this.redis.keys(pattern);
if (keys.length > 0) {
await this.redis.del(keys);
}
}
}// Publisher
await redis.publish('events', JSON.stringify({
type: 'user_login',
userId: 123,
timestamp: Date.now()
}));
// Subscriber
const subscriber = redis.duplicate();
await subscriber.subscribe('events');
subscriber.on('message', (channel, message) => {
const event = JSON.parse(message);
console.log(`Received: ${event.type}`);
});- Click "Cloud Storage Demo"
- Test "Upload Performance" with different file sizes
- Run "Download Tests" for various scenarios
Performance metrics:
File Size: 1MB
Upload: 45ms (22 MB/s)
Download: 32ms (31 MB/s)
File Size: 10MB
Upload: 380ms (26 MB/s)
Download: 290ms (34 MB/s)
class CloudStorage {
async uploadFile(file, metadata = {}) {
const key = `uploads/${Date.now()}-${file.name}`;
const buffer = await file.arrayBuffer();
const result = await this.s3.putObject(this.bucket, key, buffer, {
metadata: {
'content-type': file.type,
'original-name': file.name,
...metadata
}
});
return {
key,
etag: result.etag,
size: buffer.byteLength,
url: this.getPublicUrl(key)
};
}
async downloadFile(key) {
const object = await this.s3.getObject(this.bucket, key);
return new Blob([object], {
type: object.metadata?.['content-type']
});
}
}class CDNStorage extends CloudStorage {
constructor(s3Client, cdnDomain) {
super(s3Client);
this.cdnDomain = cdnDomain;
}
getPublicUrl(key) {
return `https://${this.cdnDomain}/${key}`;
}
async uploadWithCDN(file, options = {}) {
const result = await this.uploadFile(file, options);
// Invalidate CDN cache if needed
if (options.invalidateCDN) {
await this.invalidateCDN(result.key);
}
return {
...result,
cdnUrl: this.getPublicUrl(result.key)
};
}
}class DatabasePool {
constructor(maxConnections = 10) {
this.maxConnections = maxConnections;
this.connections = [];
this.waitingQueue = [];
}
async getConnection() {
if (this.connections.length > 0) {
return this.connections.pop();
}
if (this.connections.length < this.maxConnections) {
return this.createConnection();
}
// Wait for connection to be returned
return new Promise((resolve) => {
this.waitingQueue.push(resolve);
});
}
returnConnection(connection) {
if (this.waitingQueue.length > 0) {
const resolver = this.waitingQueue.shift();
resolver(connection);
} else {
this.connections.push(connection);
}
}
async withConnection(callback) {
const connection = await this.getConnection();
try {
return await callback(connection);
} finally {
this.returnConnection(connection);
}
}
}class TransactionManager {
constructor(database) {
this.database = database;
}
async runInTransaction(callback) {
const db = await this.database.getConnection();
try {
await db.run('BEGIN TRANSACTION');
const result = await callback(db);
await db.run('COMMIT');
return result;
} catch (error) {
await db.run('ROLLBACK');
throw error;
} finally {
this.database.returnConnection(db);
}
}
// Example usage
async transferMoney(fromId, toId, amount) {
return this.runInTransaction(async (db) => {
// Check balance
const fromAccount = await db.prepare(
'SELECT balance FROM accounts WHERE id = ?'
).get(fromId);
if (fromAccount.balance < amount) {
throw new Error('Insufficient funds');
}
// Perform transfer
await db.prepare(
'UPDATE accounts SET balance = balance - ? WHERE id = ?'
).run(amount, fromId);
await db.prepare(
'UPDATE accounts SET balance = balance + ? WHERE id = ?'
).run(amount, toId);
return { success: true, amount };
});
}
}class DatabaseMonitor {
constructor() {
this.metrics = {
connections: { active: 0, idle: 0, total: 0 },
queries: { total: 0, slow: 0, failed: 0, avgDuration: 0 },
cache: { hits: 0, misses: 0, hitRate: 0 }
};
}
recordQuery(duration, success = true) {
this.metrics.queries.total++;
this.metrics.queries.avgDuration =
(this.metrics.queries.avgDuration + duration) / 2;
if (!success) {
this.metrics.queries.failed++;
}
if (duration > 100) { // Slow query threshold
this.metrics.queries.slow++;
}
}
recordCacheAccess(hit) {
if (hit) {
this.metrics.cache.hits++;
} else {
this.metrics.cache.misses++;
}
this.metrics.cache.hitRate =
this.metrics.cache.hits /
(this.metrics.cache.hits + this.metrics.cache.misses);
}
getMetrics() {
return { ...this.metrics };
}
}class QueryProfiler {
constructor(database) {
this.database = database;
this.queries = [];
}
async profile(sql, params, operation) {
const start = performance.now();
try {
const result = await operation();
const duration = performance.now() - start;
this.queries.push({
sql,
params,
duration,
success: true,
timestamp: new Date()
});
return result;
} catch (error) {
const duration = performance.now() - start;
this.queries.push({
sql,
params,
duration,
success: false,
error: error.message,
timestamp: new Date()
});
throw error;
}
}
getSlowQueries(threshold = 100) {
return this.queries.filter(q => q.duration > threshold);
}
getQueryStats() {
const completed = this.queries.filter(q => q.success);
const failed = this.queries.filter(q => !q.success);
return {
totalQueries: this.queries.length,
successfulQueries: completed.length,
failedQueries: failed.length,
avgDuration: completed.reduce((sum, q) => sum + q.duration, 0) / completed.length,
maxDuration: Math.max(...completed.map(q => q.duration)),
slowQueries: this.getSlowQueries().length
};
}
}-- Analyze query patterns first
EXPLAIN QUERY PLAN
SELECT * FROM users WHERE email = 'test@example.com';
-- Create appropriate indexes
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created_at ON users(created_at);
CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
-- Composite indexes for multi-column queries
CREATE INDEX idx_users_active_email ON users(is_active, email)
WHERE is_active = true;
-- Partial indexes for specific use cases
CREATE INDEX idx_recent_orders ON orders(created_at)
WHERE created_at >= date('now', '-30 days');-- Use EXISTS instead of COUNT for existence checks
SELECT EXISTS(SELECT 1 FROM users WHERE email = ?) as user_exists;
-- Prefer JOINs over subqueries for better performance
SELECT u.name, o.total_amount
FROM users u
JOIN orders o ON u.id = o.user_id;
-- Use LIMIT for pagination
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 50 OFFSET 0;
-- Optimize with UNION ALL when possible
SELECT id, 'user' as type FROM users
UNION ALL
SELECT id, 'product' as type FROM products;// Use streaming for large datasets
const stream = db.prepare('SELECT * FROM large_table').iterate();
for await (const row of stream) {
processRow(row);
}
// Batch processing
const BATCH_SIZE = 1000;
let offset = 0;
while (true) {
const batch = db.prepare('SELECT * FROM table LIMIT ? OFFSET ?')
.all(BATCH_SIZE, offset);
if (batch.length === 0) break;
await processBatch(batch);
offset += BATCH_SIZE;
// Allow GC between batches
if (Bun.gc) Bun.gc();
}β SQLite performance testing and optimization β Redis integration patterns and caching β Cloud storage benchmarking techniques β Connection pooling and transaction management β Query optimization strategies β Database monitoring and profiling
- Database choice matters - Select the right database for your use case
- Connection pooling prevents resource exhaustion
- Indexing strategy dramatically impacts query performance
- Transactions ensure data consistency in complex operations
- Monitoring provides insights for continuous optimization
- Web applications with user management and sessions
- E-commerce platforms with product catalogs and orders
- Content management systems with rich media storage
- Analytics platforms requiring fast data aggregation
- Real-time applications needing pub/sub messaging
Database Integration Expert π You've completed advanced database testing and learned to:
- Benchmark multiple database systems
- Implement caching strategies
- Optimize query performance
- Monitor database health
- Scale applications effectively
- Build Optimization Tutorial - Optimize your build pipeline
- Testing Arsenal Tutorial - Master comprehensive testing
- Integration Examples - Real-world implementation
- Database API Reference
- SQL Examples - Advanced query patterns
- Performance Monitoring - Database metrics
Questions? Join our GitHub Discussions or check the Troubleshooting Guide.
Built with β€οΈ for the Bun ecosystem β’ Last updated: October 21, 2025