Performance Testing
Performance testing ensures the platform meets speed and scalability requirements.
Performance Goals
- API Response Time: < 200ms (p95)
- Page Load Time: < 2s
- Database Queries: < 100ms
- Concurrent Users: 100+ without degradation
Testing Response Times
API Endpoint Testing
// tests/performance/api-load.test.js
import { test } from '@playwright/test';
test('API response time', async ({ request }) => {
const startTime = Date.now();
const response = await request.get('/api/health');
const responseTime = Date.now() - startTime;
expect(response.status()).toBe(200);
expect(responseTime).toBeLessThan(200); // Should respond in < 200ms
});
Database Query Performance
// tests/performance/database.test.js
import { sql } from '../../src/server.js';
test('database query performance', async () => {
const startTime = Date.now();
const users = await sql`
SELECT * FROM users
WHERE email = 'test@example.com'
`;
const queryTime = Date.now() - startTime;
expect(queryTime).toBeLessThan(100); // Should query in < 100ms
});
Load Testing
Using k6
// tests/performance/load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 20 }, // Ramp up to 20 users
{ duration: '1m', target: 20 }, // Stay at 20 users
{ duration: '30s', target: 50 }, // Ramp up to 50 users
{ duration: '1m', target: 50 }, // Stay at 50 users
{ duration: '30s', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95% of requests < 500ms
http_req_failed: ['rate<0.01'], // Error rate < 1%
},
};
export default function () {
const response = http.get('https://reformer-platform.onrender.com/api/health');
check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
Running Load Tests
# Run load test
npm run test:perf
# Run with specific scenario
k6 run tests/performance/load-test.js
Monitoring Performance
Key Metrics
- Response Time - Time to first byte, total time
- Throughput - Requests per second
- Error Rate - Percentage of failed requests
- Resource Usage - CPU, memory, database connections
Performance Monitoring
// src/utils/performance-monitor.js
export function trackPerformance(endpoint, duration) {
if (duration > 1000) {
logger.warning('Slow endpoint', {
endpoint,
duration,
threshold: 1000
});
}
// Send to monitoring service
metrics.record('api.response_time', duration, {
endpoint,
environment: process.env.NODE_ENV
});
}
Performance Best Practices
- Database Indexing - Index frequently queried columns
- Query Optimization - Use EXPLAIN ANALYZE
- Caching - Cache expensive operations
- Connection Pooling - Reuse database connections
- Async Operations - Don't block the event loop