Launch spike and soak
Game launches are the highest-stakes performance events in software. The window between “game goes live” and “login servers fall over” can be under five minutes. This page covers how to plan and execute the two complementary tests that make a game ready to ship: the launch spike that validates your system can absorb the day-one storm, and the overnight soak that validates it can run cleanly for the next 72 hours.
Before you start
Section titled “Before you start”- Your game server, matchmaking, and backend APIs have each passed their individual load tests.
- The full test suite (spike + soak) should be run in the staging environment, not production.
- Alert ops and QA before running — a spike at launch-scale can cause elevated errors visible in monitoring.
- Read Test types: Spike test and Test types: Soak / endurance test for the underlying test patterns.
Part 1 — Launch-day login spike
Section titled “Part 1 — Launch-day login spike”What the launch spike tests
Section titled “What the launch spike tests”The first 10 minutes after a game goes live produce a concentrated login storm unlike anything the service will see again at steady state. Every player who has pre-registered or pre-loaded the client hits the login, authentication, and matchmaking services simultaneously. The spike test validates:
- The authentication service handles the full registration queue without 5xx responses.
- Session allocation does not fail when match demand exceeds the pre-warmed server pool.
- Leaderboard and profile services handle the simultaneous write blast at first login.
- The system recovers and stabilizes after the initial surge — not just survives it.
Load profile for a launch spike
Section titled “Load profile for a launch spike”| Phase | VUs | Duration | Notes |
|---|---|---|---|
| Baseline | 50 | 1 min | Warm state, no storm |
| Launch surge | 5 000 | 3 min | Peak login density |
| Hold at peak | 5 000 | 5 min | Sustained post-surge load |
| Ramp down | 50 | 2 min | Back to steady state |
| Recovery observation | 50 | 3 min | Watch for lingering errors |
Total run time: ~14 minutes. The recovery observation phase is critical — a system that survives the surge but continues to show errors after load drops has a resource-exhaustion problem (connection pool, thread pool, in-flight request queue) that will manifest throughout the launch day.
Taurus configuration
Section titled “Taurus configuration”execution: - executor: k6 concurrency: - const: 50 duration: 1m - const: 5000 duration: 3m - const: 5000 duration: 5m - const: 50 duration: 2m - const: 50 duration: 3m scenario: launch-login
scenarios: launch-login: script: launch-spike.jsimport http from 'k6/http';import { check, sleep } from 'k6';
export const options = { thresholds: { http_req_duration: ['p(95)<500'], // auth + session under 500 ms at p95 http_req_failed: ['rate<0.01'], // < 1 % errors at peak },};
export default function () { const headers = { 'Content-Type': 'application/json' };
// Step 1: Authenticate const authRes = http.post( 'https://auth.staging.example.com/v1/login', JSON.stringify({ username: `loadtest-user-${__VU}`, password: __ENV.TEST_PASSWORD }), { headers } ); check(authRes, { 'login 200': (r) => r.status === 200 }); if (authRes.status !== 200) return;
const token = authRes.json('access_token'); const authHeader = { headers: { Authorization: `Bearer ${token}`, ...headers } };
// Step 2: Load player profile (every player on login) const profileRes = http.get('https://api.staging.example.com/v1/players/me', authHeader); check(profileRes, { 'profile 200': (r) => r.status === 200 });
// Step 3: Enqueue for matchmaking const queueRes = http.post( 'https://matchmaking.staging.example.com/v1/queue', JSON.stringify({ mode: 'casual' }), authHeader ); check(queueRes, { 'queue 202': (r) => r.status === 202 });
sleep(2);}import Screenshot from ‘@components/Screenshot.astro’;
Part 2 — Overnight soak
Section titled “Part 2 — Overnight soak”What the overnight soak tests
Section titled “What the overnight soak tests”After the launch spike validates the day-one storm, the overnight soak validates the next 72 hours: steady-state load held for 8–12 hours to surface slow resource leaks, database connection exhaustion, and gradual latency drift. For games, the soak also validates the game-loop stability — that the game server does not accumulate lag or drop events over long session windows.
Use the same VU count as your steady-state load test — not the spike peak. The soak is not about maximum load; it is about continuous load over time.
Load profile for an overnight soak
Section titled “Load profile for an overnight soak”| Parameter | Value |
|---|---|
| VUs | Steady-state target (e.g. 1 000 concurrent players) |
| Ramp-up | 5 min |
| Hold | 8–12 h |
| Location | Same as production distribution |
| Stop mode | Duration |
execution: - executor: k6 concurrency: 1000 ramp-up: 5m hold-for: 8h scenario: overnight-soak
scenarios: overnight-soak: script: game-server-load.js # same as concurrent-player testSet a Failure criteria on error rate (> 0.5 %) and p95 message latency (> 150 ms) so MaxoPerf automatically fails the run if a leak causes degradation mid-soak — you do not need to watch the dashboard overnight.
Reading the soak result
Section titled “Reading the soak result”After the soak completes, open the Overview tab and look for:
- Latency drift. p95 message latency should be flat across 8 hours. An upward drift of more than 20 % is a signal worth investigating — it often indicates a memory or connection pool leak.
- Throughput decline. Messages per second at constant VUs should be flat. A decline signals the server is processing each tick more slowly over time (garbage collection pauses, increasing lock contention, growing data structures).
- Error rate inflection. Errors that appear only after 4–6 hours are characteristic of resource exhaustion (open file descriptors, connection pool limits, session table overflow).
Cross-reference MaxoPerf’s latency drift chart with your server’s heap metrics, open connection count, and GC pause logs to pinpoint the root cause.
Cross-linking spike and soak
Section titled “Cross-linking spike and soak”Run the launch spike first. If the spike passes all thresholds, run the overnight soak. If the soak shows drift after 4 hours, fix the leak and run the spike again to confirm the fix did not change launch-day behavior. These two tests together give you the full pre-launch performance sign-off.
Do / don’t
Section titled “Do / don’t”Do:
- Include a recovery observation window (3 min minimum) after the spike — the recovery curve is as important as surviving the peak.
- Use the same test scenario for both spike and soak so you are testing the same code paths.
- Set failure criteria before the run — you should never be in a position where you are manually deciding whether a 420 ms p95 is “acceptable” during a launch-night review.
Don’t:
- Skip the soak because the spike passed — they test different failure modes.
- Run the soak at spike-level VU count — that tests sustained stress, not steady-state stability, and will exhaust resources that would never be exhausted in normal operation.
- Use production player accounts as test identities — always use dedicated loadtest accounts with the same permission set as real players.
Where to go next
Section titled “Where to go next”- Test types: Spike test — the spike test pattern.
- Test types: Soak / endurance test — the soak test pattern.
- Daily scenarios — recurring event scenarios (patch day, raid boss, weekend soak).
- Matchmaking and lobby testing — add matchmaking to the launch-spike scenario.
- Cookbook: Scheduled runs — automate the overnight soak with MaxoPerf schedules.