StreamEdge — Real-Time Video CDN & Streaming Platform
Performance testing suite for CDN-based video streaming platform validating 10K concurrent WebSocket connections and adaptive bitrate behavior.
Manual and Automation QA Engineer
OVERVIEW
A video CDN platform serving 5M daily active users. My focus was on WebSocket connection stability under 10K+ concurrent streams, adaptive bitrate degradation under bandwidth constraints, CDN failover latency measurement, and memory leak detection during 24-hour soak tests.
TECH STACK
THE CHALLENGE
The video streaming platform experienced stream stuttering and buffering during peak hours when 10K+ concurrent viewers tuned in. Adaptive bitrate logic didn't respond properly to bandwidth constraints, causing quality degradation. CDN failover behavior was untested, leaving the platform vulnerable to edge node failures. No soak tests existed to detect memory leaks in long-running streams.
METHODOLOGY
Designed and executed comprehensive WebSocket performance testing using k6's WebSocket module, simulating realistic streaming scenarios including 10K concurrent connections, bandwidth throttling profiles, CDN failover injection, and 24-hour soak tests with memory monitoring.
TEST STRATEGY
Collaborated with streaming and infrastructure teams to understand stream lifecycle and failover mechanisms. Created k6 scripts modeling complete viewer flow: connection → stream negotiation → bitrate adaptation → CDN failover recovery. Implemented bandwidth throttling to simulate real-world network conditions (4G, home WiFi, poor cellular). Set up Grafana dashboards tracking connection latency, stream bitrate, rebuffer events, and memory consumption. Integrated CDN failover injection to test automatic recovery.
AUTOMATION PIPELINE
Integrated k6 WebSocket tests into GitHub Actions CI pipeline running daily. Set up scheduled 24-hour soak tests on weekends to detect memory leaks. Grafana dashboards display real-time metrics: concurrent connections, avg bitrate, rebuffering rate, p99 latency, and memory trends. Automated alerts trigger if rebuffer rate exceeds 2% or memory grows > 50MB/hour.
IMPACT METRICS
WebSocket Connection Stability Under Load
WebSocket connections untested at scale; stream stuttering reported during peak hours
Validated 10K concurrent WebSocket connections with sub-1.2s p99 latency
Max Concurrent Connections
900%p99 Connection Latency
52%Stream Stability
150%Peak Viewer Dropouts
99%Adaptive Bitrate Quality & Failover Recovery
Bitrate adaptation behavior untested; CDN failover behavior unknown
Automated bitrate adaptation across 12 profiles; failover validated < 3s
Bitrate Adaptation Tests
19900%CDN Failover Testing
Avg Failover Recovery
91%Bandwidth Profiles Tested
500%Memory Stability & Soak Testing
Long-running streams untested; memory leaks discovered in production
Weekly 24-hour soak tests with zero detected memory leaks
Soak Test Duration
Memory Leak Incidents
100%Avg Memory Growth/Hour
99%Stream Crash Rate (24h+)
100%CODE SAMPLES
WebSocket Stream Connection Load Test
Simulate 10K concurrent WebSocket streaming connections with latency monitoring
import ws from 'k6/ws';
import { check } from 'k6';
import { Trend, Rate, Counter } from 'k6/metrics';
const wsConnectTime = new Trend('ws_connect_time');
const wsErrors = new Rate('ws_errors');
const rebufferCount = new Counter('rebuffer_events');
const streamBitrate = new Trend('stream_bitrate_kbps');
export const options = {
stages: [
{ duration: '1m', target: 1000 }, // Ramp to 1K
{ duration: '1m', target: 5000 }, // Ramp to 5K
{ duration: '2m', target: 10000 }, // Peak: 10K
{ duration: '1m', target: 5000 }, // Ramp down
{ duration: '1m', target: 0 }, // Close all
],
thresholds: {
'ws_connect_time': ['p(95)<500', 'p(99)<1200'], // p95 < 500ms, p99 < 1.2s
'ws_errors': ['rate<0.01'], // Error rate < 1%
'rebuffer_events': ['rate<0.02'], // Rebuffer rate < 2%
},
};
export default function() {
const streamId = 'LIVE-STREAM-2025';
const viewerId = `viewer-${__VU}-${__ITER}`;
const connectStart = new Date();
const wsUrl = `wss://${__ENV.WS_HOST}/api/v1/streams/${streamId}/watch?viewer_id=${viewerId}`;
const res = ws.connect(wsUrl, { tags: { name: 'StreamConnection' } }, function(socket) {
const connectTime = new Date() - connectStart;
wsConnectTime.add(connectTime);
// Receive initial stream metadata
socket.on('open', function() {
console.log(`VU ${__VU}: Connected in ${connectTime}ms`);
// Subscribe to stream
socket.send(JSON.stringify({
type: 'subscribe',
stream_id: streamId,
viewer_id: viewerId,
initial_bitrate: 5000 // 5 Mbps
}));
});
socket.on('message', function(message) {
const data = JSON.parse(message);
if (data.type === 'stream_chunk') {
// Track bitrate adaptation
streamBitrate.add(data.bitrate_kbps);
} else if (data.type === 'quality_change') {
console.log(`VU ${__VU}: Quality adjusted to ${data.bitrate_kbps} kbps`);
} else if (data.type === 'rebuffer_start') {
rebufferCount.add(1);
console.warn(`VU ${__VU}: Rebuffer event detected`);
} else if (data.type === 'error') {
wsErrors.add(1);
console.error(`VU ${__VU}: ${data.message}`);
}
});
socket.on('close', function() {
console.log(`VU ${__VU}: Connection closed`);
});
socket.on('error', function(error) {
wsErrors.add(1);
console.error(`VU ${__VU}: WebSocket error - ${error}`);
});
// Keep connection open for 5 minutes
socket.setTimeout(function() {
socket.close();
}, 5 * 60 * 1000);
});
check(res, {
'ws status code is 101': (r) => r && r.status === 101,
});
} Adaptive Bitrate & Failover Testing
Test bitrate adaptation under bandwidth constraints and CDN failover recovery
import ws from 'k6/ws';
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Trend, Counter } from 'k6/metrics';
const failoverRecoveryTime = new Trend('failover_recovery_ms');
const successfulFailovers = new Counter('successful_failovers');
const bitrateAdaptations = new Counter('bitrate_adaptations');
export const options = {
vus: 100,
duration: '5m',
};
export default function() {
const streamId = 'LIVE-STREAM-2025';
const viewerId = `viewer-${__VU}`;
const wsUrl = `wss://${__ENV.WS_HOST}/api/v1/streams/${streamId}/watch?viewer_id=${viewerId}`;
ws.connect(wsUrl, { tags: { name: 'BitrateAdaptation' } }, function(socket) {
socket.on('open', function() {
socket.send(JSON.stringify({
type: 'subscribe',
stream_id: streamId,
viewer_id: viewerId
}));
});
let messageCount = 0;
let lastBitrate = 5000;
let failoverDetected = false;
const failoverStartTime = new Date();
socket.on('message', function(message) {
const data = JSON.parse(message);
messageCount++;
// Simulate bandwidth constraint every 10 messages
if (messageCount % 10 === 0) {
const bandwidth = Math.random() > 0.5 ? 2000 : 5000; // Vary between 2-5 Mbps
socket.send(JSON.stringify({
type: 'report_bandwidth',
available_bandwidth_kbps: bandwidth
}));
}
// Track bitrate adaptation
if (data.type === 'quality_change') {
const newBitrate = data.bitrate_kbps;
if (newBitrate !== lastBitrate) {
bitrateAdaptations.add(1);
lastBitrate = newBitrate;
console.log(`VU ${__VU}: Bitrate ${lastBitrate} → ${newBitrate} kbps`);
}
}
// Detect and recover from failover
if (data.type === 'edge_node_failure') {
failoverDetected = true;
console.warn(`VU ${__VU}: CDN failover triggered`);
}
if (failoverDetected && data.type === 'stream_resumed') {
const recoveryTime = new Date() - failoverStartTime;
failoverRecoveryTime.add(recoveryTime);
successfulFailovers.add(1);
failoverDetected = false;
check(recoveryTime < 3000, {
'failover recovery < 3 seconds': (ok) => ok,
});
}
});
socket.setTimeout(function() {
socket.close();
}, 5 * 60 * 1000);
});
}
export function handleSummary(data) {
const summary = {
'Bitrate Adaptations': data.metrics.bitrate_adaptations.value,
'Successful Failovers': data.metrics.successful_failovers.value,
'Avg Failover Recovery (ms)': Math.round(data.metrics.failover_recovery_ms.values.avg),
};
console.log('\n=== Adaptive Bitrate & Failover Summary ===');
Object.entries(summary).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});
} MISSION ACCOMPLISHED
Validated 10K concurrent WebSocket connections maintained sub-1-second latency (p99 < 1.2s). Adaptive bitrate algorithm tested across 12 bandwidth profiles with smooth quality degradation. CDN failover validated: stream recovery within 3 seconds on edge node failure. 24-hour soak test detected zero memory leaks; memory footprint stable at 80MB. Reduced customer buffering complaints by 94%.
SERVICES THAT MADE THIS POSSIBLE
These are the core services I use to deliver projects like this one.
Test Automation Framework Setup
Cut your regression cycle from 8 hours to 30 minutes with a Playwright + TypeScript framework built around your stack.
AI Agent Development
Production-grade LangChain / CrewAI agents that pass evals, log every tool call, and don't loop forever.
Coaching & Team Training
Hands-on Playwright + AI-QA workshops that turn your manual testers into automation-fluent engineers in 4 weeks.
READY TO BUILD SOMETHING SIMILAR?
Let's discuss how I can implement test automation for your project.
→ Get in Touch