Performance Testing Self-Hosted Apps with k6
How many concurrent users can your self-hosted app handle? k6 load testing tells you before your users find out the hard way.
Why Load Test?
Your app works fine with 5 users. Will it handle 500? 5,000? Load testing reveals bottlenecks before real users hit them.
What Is k6?
k6 is an open-source load testing tool by Grafana Labs. Write tests in JavaScript, run from the command line.
Basic Test
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
vus: 50, // 50 virtual users
duration: '5m', // for 5 minutes
};
export default function () {
const res = http.get('https://myapp.example.com/');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
Test Scenarios
Smoke Test
1-5 users for 1 minute. Verify the test works and the app is responsive.
Load Test
Expected concurrent users for 10-30 minutes. Does the app maintain acceptable performance?
Stress Test
Gradually increase beyond expected load. Find the breaking point.
Spike Test
Sudden burst of traffic. How does the app behave under sudden load?
Soak Test
Normal load for extended periods (hours). Find memory leaks and resource exhaustion.
Key Metrics
Common Bottlenecks
Database
Most common. Slow queries, too many connections, no connection pooling.
Memory
App consumes more memory under load than available. OOM kills follow.
CPU
Compute-intensive operations (image processing, encryption) saturate CPU.
Network
Rare for self-hosted apps, but possible with large file transfers.
Optimization Cycle
1. Run baseline load test
2. Identify bottleneck (database, CPU, memory)
3. Optimize (add index, tune config, add caching)
4. Re-run load test
5. Repeat until performance meets requirements
Before deploying on TinyPod, run a quick load test against your staging instance. Know your limits before production traffic arrives.