Performance Optimization Guide
Performance Optimization Guide
Guide to optimizing SCORM API performance and reducing latency.
Table of Contents
- Overview
- API Optimization
- Package Processing Optimization
- Session Management Optimization
- Caching Strategies
- Database Optimization
- Best Practices
Overview
Performance optimization focuses on:
- Reducing API response times
- Minimizing package processing time
- Optimizing session management
- Efficient resource usage
- Scalability improvements
API Optimization
Request Optimization
1. Use Pagination:
// ❌ Fetching all packages
const allPackages = await fetch('/api/v1/packages?tenant_id=...');
// ✅ Use pagination
const packages = await fetch(
'/api/v1/packages?tenant_id=...&page=1&limit=20'
);
2. Filter Results:
// ✅ Filter at API level
const completedSessions = await fetch(
'/api/v1/sessions?completion_status=completed&limit=50'
);
3. Select Specific Fields:
// ✅ Request only needed fields
const packages = await fetch(
'/api/v1/packages?fields=id,title,version'
);
Batch Operations
Batch Session Updates:
// ❌ Multiple individual requests
for (const session of sessions) {
await updateSession(session.id, updates);
}
// ✅ Batch update (if supported)
await batchUpdateSessions(sessions.map(s => ({
id: s.id,
updates: s.updates
})));
Connection Pooling
Reuse Connections:
// Use connection pool
const client = new APIClient({
baseURL: 'https://scorm-api.allurelms.com',
keepAlive: true,
maxConnections: 10
});
Package Processing Optimization
Package Size Optimization
1. Compress Media:
- Optimize images (WebP, compressed JPEG)
- Compress videos (H.264, appropriate bitrate)
- Minimize file sizes
2. Remove Unnecessary Files:
- Remove source files
- Remove development files
- Remove duplicate assets
3. Optimize Structure:
- Flat directory structure
- Minimize nesting
- Efficient file organization
Processing Time
Expected Processing Times:
- Small packages (<10MB): 10-30 seconds
- Medium packages (10-100MB): 30-120 seconds
- Large packages (100MB-1GB): 2-10 minutes
- Very large packages (>1GB): 10-30 minutes
Optimization Tips:
- Use multipart upload for large packages
- Process asynchronously with webhooks
- Monitor processing status
- Set appropriate timeouts
Session Management Optimization
Session Creation
1. Reuse Sessions:
// Check for existing incomplete session
const existingSession = await findIncompleteSession(
packageId,
userId
);
if (existingSession) {
return existingSession; // Reuse
}
// Create new only if needed
return await createSession(packageId, userId);
2. Batch Session Creation:
// Create multiple sessions efficiently
const sessions = await Promise.all(
userIds.map(userId => createSession(packageId, userId))
);
Progress Tracking
1. Reduce Update Frequency:
// ❌ Update on every CMI change
scormAPI.setValue('cmi.core.lesson_status', 'incomplete');
await updateSession(); // Too frequent
// ✅ Batch updates
const updates = [];
// Collect updates
updates.push({ field: 'cmi.core.lesson_status', value: 'incomplete' });
// Update periodically (e.g., every 5 seconds)
setInterval(() => updateSession(updates), 5000);
2. Use Webhooks Instead of Polling:
// ❌ Polling every second
setInterval(async () => {
const session = await getSession(sessionId);
// Check status
}, 1000);
// ✅ Use webhooks
await subscribeToWebhook('session.completed', (event) => {
// Handle completion
});
Caching Strategies
Client-Side Caching
1. Cache Package Metadata:
const packageCache = new Map();
async function getPackage(packageId: string) {
if (packageCache.has(packageId)) {
return packageCache.get(packageId);
}
const pkg = await fetchPackage(packageId);
packageCache.set(packageId, pkg);
return pkg;
}
2. Cache Session Data:
// Cache session data with TTL
const sessionCache = new Map();
async function getSession(sessionId: string) {
const cached = sessionCache.get(sessionId);
if (cached && cached.expiresAt > Date.now()) {
return cached.data;
}
const session = await fetchSession(sessionId);
sessionCache.set(sessionId, {
data: session,
expiresAt: Date.now() + 60000 // 1 minute TTL
});
return session;
}
HTTP Caching
Use ETags:
const response = await fetch('/api/v1/packages/pkg_abc123', {
headers: {
'X-API-Key': apiKey,
'If-None-Match': cachedETag // Use cached ETag
}
});
if (response.status === 304) {
// Use cached data
return cachedData;
}
Database Optimization
Query Optimization
1. Use Indexes:
-- Indexes on frequently queried columns
CREATE INDEX idx_packages_tenant_id ON scorm_packages(tenant_id);
CREATE INDEX idx_sessions_user_package ON scorm_sessions(user_id, package_id);
2. Limit Result Sets:
// Always use LIMIT
const sessions = await db.sessions.findMany({
where: { tenant_id: tenantId },
take: 20, // Limit results
orderBy: { created_at: 'desc' }
});
3. Select Only Needed Fields:
// Select only required fields
const packages = await db.packages.findMany({
where: { tenant_id: tenantId },
select: {
id: true,
title: true,
version: true
// Don't select large fields unless needed
}
});
Best Practices
1. Minimize API Calls
// ❌ Multiple calls
const package = await getPackage(packageId);
const sessions = await getSessions(packageId);
const reports = await getReports(packageId);
// ✅ Single call with related data
const data = await getPackageWithDetails(packageId);
2. Use Async Processing
// Process package asynchronously
const upload = await uploadPackage(file);
// Don't wait for processing
await subscribeToWebhook('package.processing.completed', (event) => {
// Handle completion
});
3. Implement Retry Logic
async function fetchWithRetry(url: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fetch(url);
} catch (error) {
if (i === maxRetries - 1) throw error;
await delay(Math.pow(2, i) * 1000);
}
}
}
4. Monitor Performance
// Track API call performance
async function trackPerformance(fn: () => Promise<any>) {
const start = Date.now();
const result = await fn();
const duration = Date.now() - start;
console.log(`Operation took ${duration}ms`);
if (duration > 5000) {
console.warn('Slow operation detected');
}
return result;
}
Related Documentation
- Scaling Guide - Scaling strategies
- Caching Strategies - Detailed caching guide
- API Reference - Complete API docs
Last Updated: 2025-01-15