Hoe een zonsverduistering de blinde vlek van auto-scaling in game-backends blootlegde
Kort samengevat
Leer hoe een zonsverduistering de blinde vlek van auto-scaling in game-backends onthult en implementeer anomaliedetectie om pieken op te vangen.
Wanneer 75% van je spelers in 30 minuten verdwijnt
Op 12 augustus 2025 mat Cloudflare iets waar elke backend-engineer ongemakkelijk van zou moeten worden: het internetverkeer in IJsland stortte tijdens de maximale obscuratie van de totale zonsverduistering met ruwweg 75% in, om een paar minuten later weer op te veren. Spanje en Portugal lieten vrijwel identieke curves zien. Miljoenen mensen — waaronder jouw spelers — legden hun apparaten weg en gingen naar buiten.
Voor gamestudio's met live-service-backends is zo'n plotselinge, geografisch geconcentreerde verkeersschommeling geen hypothese. Het is precies het scenario waarop reactieve auto-scaling faalt. Als je serverfleet schaalt op basis van het aantal requests van de afgelopen vijf minuten, leidt een daling van 75% gevolgd door een opleving van 120% tien minuten later tot óf overbodig geprovisioneerde servers die geld verbranden, óf — erger — een te kleine fleet die de terugkerende piek niet kan absorberen.
Dit artikel ontleedt precies wat Cloudflare tijdens de zonsverduistering waarnam, legt uit waarom standaard reactief schalen faalt bij voorspelbare anomalieën, en laat stap voor stap zien hoe je verkeersbewuste schaallogica in je game-backend bouwt — met een werkend codevoorbeeld en concrete drempelwaarden die je vandaag nog kunt toepassen.
De Cloudflare-data: een schoolvoorbeeld van een anomalie
Cloudflare's analyse gebruikte HTTP-request-buckets van vijf minuten in de getroffen landen, en vergeleek het verkeer op de dag van de zonsverduistering met een baseline van een normale dag. De bevindingen waren ondubbelzinnig:
- IJsland liet de steilste daling zien — ongeveer 70–75% onder de baseline bij maximale obscuratie.
- Noord-Spanje zag dalingen van 40–50% onder de baseline.
- Portugal vertoonde reducties van 30–40%, waarbij de diepste dip exact samenviel met het moment van de maximale zonsverduistering.
- Het herstel was abrupt. Binnen 15–20 minuten na het einde van de zonsverduistering keerde het verkeer terug naar de baseline, en schoot daarna 10–15% door toen mensen terugkeerden naar hun apparaten.
Het cruciale detail: de dip wachtte niet op het moment van maximale duisternis. Het verkeer begon 20–30 minuten vóór de maximale obscuratie te dalen, omdat mensen naar buiten gingen en stopten met het gebruik van hun apparaten. Deze voorrand is belangrijk, omdat het een goed geïnstrumenteerd systeem een venster geeft om te reageren — maar alleen als je erop let.
Dit patroon is niet uniek voor zonsverduisteringen. Cloudflare documenteerde een vrijwel identieke curve tijdens de WK-finale van 2026, en elk groot sportevenement, feestdag of cultureel moment levert dezelfde vorm op: een langzaam weglekkend begin, een scherp dal en een herstelpiek.
Waarom reactieve auto-scaling faalt bij voorspelbare anomalieën
De meeste game-backends gebruiken een van twee schaalstrategieën:
- Reactief (op drempelwaarden): Schaal op wanneer de CPU boven 70% komt of de requestlatentie boven 200 ms. Schaal af wanneer het gebruik onder 30% zakt.
- Predictief (gepland): Schaal naar een vooraf bepaalde capaciteit op geplande tijden (bijv. "schaal naar 200 instances op vrijdag om 18:00").
Reactief schalen heeft een fatale fout zodra verkeer plotseling daalt: de cooldownperiode. De meeste auto-scalinggroepen hanteren een cooldown van 3–10 minuten tussen schaalacties om schommelingen te voorkomen. Wanneer het verkeer in 20 minuten met 75% daalt, verwijdert het schaalsysteem wel instances, maar niet snel genoeg om de daling bij te benen. Het resultaat: je betaalt voor idle capaciteit.
Het echte probleem is het herstel. Wanneer het verkeer terugveert, moet reactief schalen:
- De toename detecteren (1–2 minuten verhoogde metrics)
- Het schaalbeleid evalueren (30 seconden)
- Nieuwe instances starten (60–180 seconden voor cloud-VM's, langer bij koude containerstarts)
- Wachten tot instances de health checks doorstaan en zich bij de load balancer voegen (30–60 seconden)
Dat is een reactievertraging van 3–5 minuten vanaf het moment dat het verkeer begint te stijgen tot het moment dat nieuwe capaciteit daadwerkelijk requests bedient. Tijdens een herstelpiek na een zonsverduistering, de rust van een WK-wedstrijd of een seizoensgebonden event in je game, overstelpen spelers die binnen een venster van 15 minuten terugkeren je resterende instances voordat nieuwe online komen.
Hier is een vereenvoudigde visualisatie van het faalpatroon:
Timeline (minutes): -30 -10 0 +5 +15 +20
Traffic: 100% 70% 25% 60% 115% 100%
↘ ↗
Drops Surge begins
Reactive scaling: ████████████▓▓▓▓▓▓▓▓░░░░░░░░░████████
Slow Remove Lag New instances
to too finally online
react late
De ░░░-zone is waar je spelers overbelaste servers raken en je matchmaking-wachtrij een timeout veroorzaakt.
Technische deep-dive: verkeersvoorspelling met anomaliedetectie bouwen
De oplossing is om reactief schalen aan te vullen met anomaliedetectie die historische patronen en verwachte events begrijpt. Hier is een werkende Python-implementatie van een verkeersanomaliedetector die je in je monitoringpipeline kunt integreren:
import numpy as np
from datetime import datetime
from dataclasses import dataclass
from enum import Enum
class AnomalyDirection(Enum):
DROP = "drop"
SURGE = "surge"
NONE = "none"
@dataclass
class AnomalyResult:
is_anomaly: bool
direction: AnomalyDirection
percent_change: float
deviation_sigma: float
recommended_action: str
confidence: float
class TrafficAnomalyDetector:
"""
Compares live traffic against per-hour, per-day-of-week baselines
to detect drops and surges that exceed a standard-deviation threshold.
Designed for game backends where traffic follows weekly patterns
(weekday evenings vs. weekend afternoons) but gets disrupted
by real-world events: eclipses, sports finals, holidays.
"""
def __init__(self, sensitivity: float = 2.0, lookback_weeks: int = 6):
self.sensitivity = sensitivity # standard deviations for alert
self.lookback_weeks = lookback_weeks # weeks of history to build baselines
self.hourly_baselines = {}
def build_baselines(self, historical_rps: dict[tuple[int, int], list[float]]):
"""
Build per-(hour, day_of_week) baselines from historical requests/sec.
Args:
historical_rps: Dict mapping (hour 0-23, dow 0-6) to list of
average RPS samples from previous weeks.
"""
for key, samples in historical_rps.items():
if len(samples) < 3:
continue
self.hourly_baselines[key] = {
'mean': np.mean(samples),
'std': np.std(samples),
'p5': np.percentile(samples, 5),
'p95': np.percentile(samples, 95),
}
def evaluate(self, current_rps: float, timestamp: datetime) -> AnomalyResult:
"""
Evaluate current traffic against the historical baseline.
Returns an AnomalyResult with recommended scaling action.
"""
key = (timestamp.hour, timestamp.weekday())
baseline = self.hourly_baselines.get(key)
if not baseline or baseline['std'] == 0:
return AnomalyResult(
is_anomaly=False,
direction=AnomalyDirection.NONE,
percent_change=0.0,
deviation_sigma=0.0,
recommended_action="maintain",
confidence=0.0,
)
deviation = (current_rps - baseline['mean']) / baseline['std']
pct_change = (current_rps - baseline['mean']) / baseline['mean'] * 100
is_anomaly = abs(deviation) > self.sensitivity
if not is_anomaly:
direction = AnomalyDirection.NONE
action = "maintain"
elif deviation < 0:
direction = AnomalyDirection.DROP
# Don't scale down aggressively during drops — wait for recovery
action = "hold_capacity" if abs(deviation) > 3.0 else "scale_down_cautious"
else:
direction = AnomalyDirection.SURGE
# Pre-scale aggressively on surges
action = "scale_up_aggressive" if deviation > 3.0 else "scale_up_moderate"
# Confidence increases with sample count and deviation magnitude
confidence = min(1.0, abs(deviation) / 5.0)
return AnomalyResult(
is_anomaly=is_anomaly,
direction=direction,
percent_change=round(pct_change, 1),
deviation_sigma=round(deviation, 2),
recommended_action=action,
confidence=round(confidence, 2),
)
# --- Example usage ---
detector = TrafficAnomalyDetector(sensitivity=2.0, lookback_weeks=6)
# Simulated baselines: (hour, day_of_week) -> past RPS readings
from collections import defaultdict
import random
np.random.seed(42)
history = defaultdict(list)
for _ in range(6): # 6 weeks of history
for dow in range(7):
for hour in range(24):
# Typical pattern: low overnight, peak in evening
base = {
range(0, 6): 200,
range(6, 12): 800,
range(12, 18): 1500,
range(18, 24): 4000,
}
for time_range, peak in base.items():
if hour in time_range:
history[(hour, dow)].append(
peak + np.random.normal(0, peak * 0.15)
)
detector.build_baselines(history)
# Simulate the eclipse: 7 PM (peak hour) with traffic at 25% of normal
eclipse_time = datetime(2025, 8, 12, 19, 5) # 7:05 PM, Tuesday
result = detector.evaluate(current_rps=1000, timestamp=eclipse_time)
print(f"Anomaly detected: {result.is_anomaly}")
print(f"Direction: {result.direction.value}")
print(f"Change: {result.percent_change}%")
print(f"Deviation: {result.deviation_sigma}σ")
print(f"Action: {result.recommended_action}")
print(f"Confidence: {result.confidence}")
Als je dit tegen de gesimuleerde zonsverduisteringsdata draait, levert dat output op zoals:
Anomaly detected: True
Direction: drop
Change: -75.0%
Deviation: -4.82σ
Action: hold_capacity
Confidence: 0.96
Het belangrijkste inzicht is de hold_capacity-aanbeveling bij dramatische dalingen. Standaard reactief schalen zou instances agressief afbreken. De anomaliedetector zegt: dit is te groot en te plotseling voor een normale verkeersdaling — er gebeurt iets externs. Schaal niet af. Dit voorkomt het pijnlijke haastwerk om opnieuw te provisioneren wanneer het verkeer terugkeert.
Voor de herstelpiek (wanneer het verkeer terugkeert op 115% van de baseline) geeft de detector scale_up_moderate af, want hoewel de piek de statistische baseline overschrijdt, valt hij binnen het verwachte herstelvenster na een grote daling — je wilt opschalen, maar niet tot het extreme dat een werkelijk ongekende spike zou triggeren.
Anomaliedetectie integreren in je scaling-pipeline
De bovenstaande detector draait onafhankelijk van je scaling-controller. Zo past hij in een productiepipeline:
┌──────────────┐ ┌─────────────────┐ ┌──────────────────┐
│ Metrics │────▶│ Anomaly │────▶│ Scaling │
│ Ingestion │ │ Detector │ │ Controller │
│ (Prom/Graf) │ │ │ │ │
└──────────────┘ │ • Baselines │ │ • Aggressive │
│ • Per-hour │ │ • Cautious │
│ comparison │ │ • Hold │
│ • Direction + │ │ │
│ confidence │ └────────┬─────────┘
└─────────────────┘ │
┌───────▼────────┐
│ Server Fleet │
│ (VMs / Pods) │
└────────────────┘
Stap 1 — Metrics-ingestie: Verzamel RPS per minuut of per vijf minuten van je load balancer of API-gateway. Tag metrics per regio (IJsland, Spanje, enz.) zodat je geografisch gecorreleerde dalingen kunt detecteren.
Stap 2 — Baseline opbouwen: Train elke week de baselines opnieuw met de laatste 6–8 weken aan data. Sluit anomale dagen (launches, grote patches, bekende incidenten) uit van de trainingsset. Dit voorkomt dat eerdere verkeerspieken je standaarddeviatie opblazen en de detector minder gevoelig maken.
Stap 3 — Anomalie-evaluatie: Voer elke vijf minuten de huidige RPS in de detector. Als deze hold_capacity of scale_up_aggressive retourneert, stuur dan met een prioriteitsoverride een schaalinstructie naar je controller.
Stap 4 — Scaling-controller: Implementeer drie schaalmodi op basis van de aanbeveling van de detector:
maintain— de standaard reactieve schaallogica wordt normaal uitgevoerdhold_capacity— schaal-omlaagacties uitschakelen voor de komende 30 minuten; een minimum aantal instances toepassen gelijk aan het huidige aantalscale_up_aggressive/scale_down_cautious— de doelcapaciteit aanpassen met specifieke percentages in plaats van te wachten op drempelwaarden
Voor studio's die dedicated server-fleets draaien (UEFN, custom Unreal dedicated servers of headless Unity-instances), draait deze pipeline naast je bestaande orchestrator als een beleidsoverride-laag. Je vervangt je auto-scaler niet — je geeft hem betere informatie over wanneer hij zijn eigen reactieve logica moet vertrouwen of wantrouwen.
Gamespecifieke context: wanneer maakt dit echt uit?
Je denkt misschien: "Ik draai een kleine indie-multiplayergame, geen wereldwijde CDN. Heeft een zonsverduistering echt invloed op mij?" Waarschijnlijk niet direct. Maar het onderliggende patroon — voorspelbare, externe events die verkeersanomalieën veroorzaken — duikt voortdurend op in game-operations:
Seizoensgebonden events en contentdrops
Wanneer je een seizoensgebonden event plant (leaderboards resetten, tijdelijke modes, vakantiecontent), creëer je een zelfveroorzaakte verkeerspiek. Spelers loggen binnen het eerste uur in en genereren 3–8x het normale requestvolume voor authenticatie, inventory-opzoekingen en matchmaking-calls. Als je backend reactief schaalt, worden de eerste 30 minuten van je event een slechtere ervaring voor iedereen.
Regionale toernooien en competitieseizoenen
Een regionaal toernooivenster (bijv. 18:00–21:00 lokale tijd) zorgt voor geconcentreerde vraag in één geografische zone. Je weet precies wanneer het begint en eindigt. Reactief schalen in die regio loopt achter op de piek en provisiont vervolgens te veel capaciteit tijdens de cooldown na het toernooi.
Concurreren met grote releases
Wanneer een AAA-titel uitkomt, zakt het verkeer van je game vaak 20–40% gedurende 2–3 dagen, omdat spelers de nieuwe release bekijken. Reactief schalen blijft compute verbranden aan instances die niemand gebruikt. Omgekeerd krijg je een herstelpiek als de launch van die game hapert (serverproblemen, slechte reviews) en spelers terugkeren.
Platformbrede events
Steam-sales, PlayStation State of Play, Xbox-showcases en Nintendo Directs zorgen allemaal voor meetbare verkeersverschuivingen. Een studio die tijdens zo'n presentatie in een sizzle reel van 15 seconden wordt genoemd, kan in minder dan 10 minuten een verkeerspiek van 500% zien — veel te snel voor alleen reactief schalen.
Elk van deze scenario's heeft baat bij dezelfde anomaliebewuste aanpak die hierboven is gedemonstreerd. De eclipsdata van Cloudflare vormen gewoon een heldere, grootschalige, datagedragen illustratie van hoe een verkeersschommeling van 75% er in de praktijk uitziet en hoe snel die zich ontwikkelt. De discussie over zero-waste serverarchitectuur voor Fortnite verkent vergelijkbaar terrein — kosten minimaliseren tijdens vensters met laag verkeer zonder het vermogen om op pieken te reageren op te offeren.
Best practices voor anomaliebestendige game-backends
1. Bouw baselines per regio en per uur — niet globaal. De zonsverduisteringsdip in IJsland was 75%. In Zuid-Frankrijk was die 5%. Een wereldwijd gemiddelde had beide gemaskeerd. Als je game ook maar een bescheiden internationaal bereik heeft, segmenteer je verkeer dan per continent of tijdzone. Een dip door een WK-finale in Argentinië betekent niets voor je Zuidoost-Aziatische spelersbasis.
2. Gebruik rolling exclusions voor je eigen events. Wanneer je een contentupdate lanceert of een gepland event draait, markeer die uren dan als anomalieën in je trainingsdata. Anders behandelt je baseline je eigen updates als normaal verkeer, waardoor de detector minder gevoelig wordt voor echte externe events.
3. Implementeer een "hold capacity"-modus, niet alleen "scale up" en "scale down". De meeste engineers beschouwen schalen als een operatie in twee richtingen. De zonsverduisteringsdata laat zien waarom je een derde modus nodig hebt: hold. Wanneer verkeer plotseling daalt en de anomaliedetector dit als een extern event markeert, houd dan je huidige aantal instances vast. Dit kost wat geld aan idle compute, maar voorkomt de catastrofale vertraging wanneer het verkeer terugkeert. Het kostenverschil tussen 100 idle instances 15 minuten vasthouden en haastig 80 nieuwe instances lanceren tijdens een spelerspiek is triviaal: de idle compute is voorspelbaar en gebudgetteerd, terwijl de piekchaos leidt tot spelersverloop, negatieve reviews en forumreacties.
4. Stel alerts in op de voorrand, niet op het dal. Cloudflare's data toont dat het verkeer 20–30 minuten vóór de piek van de zonsverduistering daalt. Als je detector is afgesteld om te triggeren bij 3σ-afwijking, vang je de daling vroeg, terwijl de afname nog gematigd is. Stel je alertdrempel in op 1,5–2σ met een rolling window van 10 minuten voor detectie van de voorrand, en een drempel van 3σ voor bevestiging van een grote anomalie.
5. Schaal vooraf voor voorspelbare events met hard-coded schema's. Voor events die je zelf beheert (je eigen seizoenslanceringen, geplande toernooien) moet je helemaal niet op auto-scaling vertrouwen. Provision de capaciteit direct. Auto-scaling is voor dingen waar je geen rekening mee hebt gehouden. Hard-coded schaalvensters zijn voor dingen die je drie weken geleden in je projectmanagementtool hebt gezet.
Als je je eigen infrastructuur draait, is het implementeren van de anomaliedetector en schedulingslogica, het afstemmen van drempelwaarden, het bouwen van dashboards en het testen van de pipeline realistisch gezien twee tot vier weken backend-engineerwerk. Dit is het soort fundamentele infrastructuur dat horizOn als managed service afhandelt — verkeersbewuste schaalbeleidsregels zijn ingebouwd in het platform, zodat jij je kunt richten op gamelogica in plaats van anomaliedetectie op infra-niveau.
Wat je nu moet doen
Als je een live multiplayer-game of een online-enabled titel draait, neem deze week dan 30 minuten de tijd om je huidige scaling-configuratie te auditen:
- Controleer je cooldown-timers. Zijn ze kort genoeg om te reageren op een verkeersschommeling van 20 minuten? De meeste staan standaard op 5–10 minuten, wat op het randje is.
- Bekijk je verkeersgeschiedenis van de afgelopen 3 maanden. Zoek de drie grootste dips. Correleer ze met gebeurtenissen in de echte wereld (feestdagen, competities, launches van concurrenten). Dit vertelt je of je al door dit patroon bent getroffen zonder dat je het doorhad.
- Test je scale-down-gedrag. Simuleer (of vind een echt venster met laag verkeer) waarin het verkeer 15 minuten met 50% daalt en daarna terugkeert naar normaal. Meet hoe lang je fleet erover doet om volledig te herstellen. Dat getal — de hersteltijd na een plotselinge terugkeer — is de belangrijkste latentiemetric in je backend die de meeste teams nooit meten.
De zonsverduistering was een zeldzaam event, maar het verkeerspatroon dat het opleverde treft game-servers elke week in minder dramatische vorm. Door nu anomaliebewust schalen te bouwen, merken je spelers de volgende nooit op.
Klaar om te stoppen met het helemaal zelf bouwen van verkeersvoorspelling? Probeer horizOn gratis en laat managed infrastructuur de schaalcomplexiteit afhandelen terwijl jij de game uitbrengt.
Bron: Totale eclips van het internet: verkeersimpact in IJsland, Spanje en Portugal