Graceful degradation ontwerpen bij LLM-uitval
Wanneer een applicatie afhankelijk is van externe Large Language Model (LLM) API's, is onbeschikbaarheid geen incidenteel verschijnsel maar een gegeven. Netwerkstoringen, capaciteitsproblemen bij providers en onverwachte foutreacties behoren tot de dagelijkse praktijk. Wanneer standaardmechanismen zoals retries of tijdelijke wachttijden geen oplossing meer bieden, voorkomt een strategie voor graceful degradation dat de gehele applicatie vastloopt.
Graceful degradation betekent dat een systeem gecontroleerd terugschakelt naar een beperktere modus wanneer een afhankelijkheid faalt. In plaats van een generieke foutmelding te tonen of een foutcode 500 aan de gebruiker te retourneren, levert de applicatie een deels functioneel antwoord. De kunst van het ontwerpen van robuuste integraties ligt in het vooraf bepalen welke functionaliteit essentieel is en welke onderdelen tijdelijk kunnen worden vereenvoudigd of weggelaten.
Let op: Dit artikel behandelt de architectuur die in werking treedt wanneer retries, timeouts en netwerkherstel zijn uitgeput. Voor de basisinrichting van netwerkherstel verwijzen we naar de artikelen over retries en backoff en timeouts en cancellation.
Faalmodi bij LLM-afhankelijkheden
Het bouwen van een robuust degradatiemechanisme begint bij het onderscheiden van de verschillende manieren waarop een LLM-eindpunt kan falen. Elk type fout vereist namelijk een specifieke reactie in de applicatie-architectuur.
1. Volledige provider-uitval
Bij een volledige uitval geeft het API-eindpunt geen gecontroleerd antwoord meer. Dit kan zich uiten in een HTTP 500, 502 of 503 foutcode, of in het volledig onbereikbaar zijn van het domein (DNS- of TLS-fouten). In dit scenario is direct duidelijk dat het eindpunt onbeschikbaar is en kan de applicatie meteen overschakelen op een alternatieve route.
2. Sterk verhoogde latency
Een verraderlijker faalmodus is een extreem trage reactie van het model. Het eindpunt geeft geen expliciete foutmelding, maar het antwoord laat tientallen seconden op zich wachten. Voor de eindgebruiker is dit vrijwel gelijk aan een uitval. Als de responstijd de ingestelde grenswaarden overschrijdt, dient het systeem het verzoek af te breken en een sneller alternatief aan te spreken.
3. Rate-limiting (HTTP 429)
Wanneer het applicatieverkeer de ingestelde limieten per minuut (RPM) of tokens per minuut (TPM) overschrijdt, retourneert de provider een HTTP 429 statuscode. Hoewel de dienst zelf operationeel is, kan de specifieke API-sleutel op dat moment geen verzoeken meer afhandelen. Dit vraagt om het tijdelijk omleiden van verzoeken naar een andere provider of een ander account.
4. Afgekapte of stilgevallen streams
Bij het gebruik van streaming responses kan een verbinding halverwege de gegenereerde tekst verbreken. Het systeem ontvangt de eerste tokens correct, maar de stream valt stil zonder dat er een geldige afsluitende JSON-chunk of stop-token binnenkomt. De applicatie moet in staat zijn om de reeds ontvangen tekst op te vangen en te bepalen of deze voldoende is, dan wel het ontbrekende deel via een secundair model aan te vullen.
5. Stille kwaliteitsdegradatie
Een van de lastigste faalmodi is kwaliteitsdegradatie zonder dat er een HTTP-foutcode optreedt. Een provider kan bij zware belasting overschakelen op een sterk gecomprimeerde kwantisatie van een model, of verzoeken intern omleiden naar een kleiner model. Het systeem geeft weliswaar een HTTP 200 OK terug, maar het resultaat bevat hallucinaties, ontbrekende structuur of weigert instructies op te volgen. Dit vereist validatielogica aan de ontvangende kant die de output controleert op minimale kwaliteits- en structuureisen.
De hiërarchie van fallback-lagen
Een effectief degradatie-ontwerp gebruikt een gelaagde structuur van alternatieven. Wanneer de primaire route faalt, zakt het verzoek af naar de eerstvolgende beschikbare laag. Deze volgorde moet zorgvuldig worden samengesteld om de balans tussen kwaliteit, latentie en functionaliteit te bewaren.
| Prioriteit | Fallback-laag | Kwaliteitsimpact | Latentie-impact |
|---|---|---|---|
| 1 (Primair) | Groot model bij primaire provider | Geen (0%) | Standaard |
| 2 | Ander model bij dezelfde provider | Gering | Gelijk of lager |
| 3 | Vergelijkbaar model bij andere provider | Gering tot matig | Variabel |
| 4 | Lokaal of kleiner gehost model | Merkbaar | Zeer laag |
| 5 | Semantisch gecachet antwoord | Afhankelijk van hit | Extreem laag |
| 6 (Ultiem) | Deterministische regelgebaseerde route | Functioneel minimaal | Verwaarloosbaar |
Lokaal model als noodscenario
In de keten van fallbacks spelen lokale of dedicated gehoste modellen een cruciale rol. Wanneer externe API-providers niet bereikbaar zijn, kan een lokaal model kiezen uitkomst bieden om kritieke basisfuncties operationeel te houden. Door gebruik te maken van lokale modellen achter een API behoudt de applicatie een gegarandeerde ondergrens van verwerkingscapaciteit, ongeacht externe netwerk- of providerstoringen.
Gecachete antwoorden en regelgebaseerde valnetten
Als ook kleine of lokale modellen niet beschikbaar zijn of te veel tijd kosten, kan het systeem terugvallen op caching van LLM-antwoorden. Bij sterk gelijkende vragen wordt een eerder goedgekeurd antwoord geserveerd. De laatste laag in de piramide is een volledig deterministische fallback. Denk hierbij aan een vast sjabloon, een eenvoudige zoekopdracht in een database, of een vooraf gedefinieerd antwoord waarin de gebruiker direct wordt geholpen zonder de inzet van kunstmatige intelligentie.
Wanneer je juist NIET moet failoveren
Het automatisch omleiden van verzoeken naar een secundaire route lijkt altijd een goede keuze, maar er zijn situaties waarin een automatische failover schadelijk is voor de gegevensintegriteit of de gebruikerservaring.
- Niet-idempotente acties: Wanneer de LLM-aanroep gekoppeld is aan een actie die een toestand veranderd (zoals het aanmaken van een reservering, het versturen van een e-mail of een financiële transactie), mag een onderbroken verzoek niet blind opnieuw naar een ander model gestuurd worden. Als het eerste verzoek op de achtergrond alsnog is verwerkt, leidt een failover tot dubbele acties.
- Tool-calls met bijwerkingen: Als de LLM bezig was met het uitvoeren van externe functies (function calling) en het proces valt stil halverwege de uitvoering, is de exacte toestand onbekend. Failover naar een ander model kan ertoe leiden dat reeds uitgevoerde stappen opnieuw worden aangeroepen.
- Complexe logische taken met strenge kwaliteitseisen: Indien de taak het opstellen van een juridisch document of een ingewikkelde code-analyse betreft, kan een kleiner fallback-model subtiele fouten maken. In dat geval is het beter om een expliciete foutmelding aan te reiken dan een antwoord van onvoldoende niveau te genereren.
Circuit breakers en health-signalen
Om te voorkomen dat een applicatie elk afzonderlijk verzoek laat vastlopen op een kapotte externe provider, wordt een circuit breaker patroon toegepast. Een circuit breaker monitort het aantal fouten en de latency van de uitgaande verzoeken en kent drie toestanden:
In de Gesloten toestand verlopen alle verzoeken normaal naar de primaire provider. Zodra het percentage fouten of de gemiddelde latency gedurende een vastgestelde tijdsinterval boven een vooraf ingestelde drempelwaarde komt, springt het circuit op Open. In deze stand worden nieuwe verzoeken direct omgeleid naar de fallback-route, zonder de primaire provider te belasten.
Na een ingestelde afkoelperiode schakelt de breaker over naar de Half-Open toestand. Een klein percentage van het testverkeer wordt doorgestuurd naar de primaire provider. Als deze testverzoeken succesvol verwerkt worden, klapt het circuit weer dicht en wordt de normale route hersteld. Mislukken de tests, dan keert de breaker direct terug naar de Open toestand.
// Voorbeeld van een eenvoudige toestandcontrole in pseudo-code
if (circuitBreaker.isOpen()) {
return runFallbackRoute(request);
}
try {
Response response = primaryProvider.send(request);
circuitBreaker.recordSuccess();
return response;
} catch (ApiException e) {
circuitBreaker.recordFailure();
return runFallbackRoute(request);
}
Flapperen voorkomen
Een veelvoorkomend probleem bij geautomatiseerde failover is flapperen: het voortdurend heen-en-weer schakelen tussen de primaire route en de fallback-route. Dit ontstaat wanneer de drempelwaarden te strikt zijn afgesteld of de testintervallen te kort zijn. Flapperen veroorzaakt een onvoorspelbare latency en wisselende antwoordkwaliteit voor de gebruiker. Dit kan worden voorkomen door gebruik te maken van sliding-window tellingen voor foutpercentages, hysteresis in de drempelwaarden en exponentiële wachttijden voor de Half-Open toestand.
Gebruikerservaring in beperkte modus
Graceful degradation betreft niet alleen de technische infrastructuur, maar ook de communicatie richting de eindgebruiker. Het transparant communiceren over de status van het systeem voorkomt frustratie.
Wanneer een applicatie overschakelt op een beperktere modus, moet dit visueel duidelijk worden gemaakt. Dit kan door middel van een subtiele melding in de interface, waarin wordt aangegeven dat het systeem op dit moment op een vereenvoudigde stand draait. Functies die afhankelijk zijn van het uitgevallen model (zoals het genereren van afbeeldingen of diepgaande analyses) kunnen tijdelijk worden uitgeschakeld of gedimd weergegeven.
Door daarnaast de verwachtingen aan te passen — bijvoorbeeld door aan te geven dat antwoorden korter kunnen zijn dan gebruikelijk — begrijpt de gebruiker waarom het resultaat verschilt van de normale situatie. Meer achtergronden over het analyseren van prestatieverschillen zijn te vinden in het artikel over snelheid meten.
Vooraf vastleggen van kwaliteitsniveaus en testen
Het succes van graceful degradation staat of valt met de voorbereiding. Het is onverstandig om tijdens een actieve storing pas na te denken over welke compromissen acceptabel zijn. Teams moeten vooraf per functie vastleggen wat het minimaal acceptabele kwaliteitsniveau is (de zogenaamde Minimum Viable Service Level).
Het proces om dit in te richten omvat vier duidelijke stappen:
- Functie-inventarisatie: Breng alle LLM-afhankelijke functies in de applicatie in kaart en categoriseer ze op basis van hun kritiekheid (bijv. kritiek, belangrijk, optioneel).
- Fallback-definitie: Bepaal per functie welke alternatieve route (kleiner model, cache, statische tekst) ingezet wordt bij uitval en wat de impact op de uitvoer is.
- Automatische evaluatie: Richt geautomatiseerde testsets in waarmee de kwaliteit van de fallback-routes continu wordt getoetst aan de hand van benchmark-vragen.
- Chaos engineering: Simuleer actief storingen in een test- of stagingomgeving. Blokkeer API-sleutels, introduceer kunstmatige vertragingen en verbreek netwerkverbindingen om te valideren of de circuit breakers en fallback-ketens correct functioneren.
Door deze mechanismen periodiek te testen, blijft het systeem voorbereid op echte storingen en kan een hoge mate van beschikbaarheid worden gegarandeerd, zelfs wanneer de onderliggende AI-providers kampen met ernstige onderbrekingen.

