Prioriteitswachtrijen voor LLM-taken
Wanneer applicaties intensief gebruikmaken van grote taalmodellen (LLM's), wordt het beheer van verzoeken een cruciaal onderdeel van de infrastructuur. Het verwerken van een tekst- of tekst-naar-code-aanroep verschilt fundamenteel van traditionele REST- of GraphQL-interfaces. In een conventionele webomgeving duren databankvragen of microservice-aanroepen meestal tussen de 5 en 200 milliseconden. Een LLM-aanroep vergt daarentegen honderden milliseconden tot tientallen seconden, en bij complexe redeneertaken of uitgebreide documenten zelfs meerdere minuten. Deze hoge latentie maakt wachtrijbeheer bij LLM-integraties een complex vraagstuk.
Wanneer een traditionele wachtrij volloopt bij een kortstondige piek, herstelt het systeem zich vaak binnen enkele seconden nadat de druk afneemt. Bij LLM-taken werkt dit anders: omdat elke taak gedurende een lange periode capaciteit bezet op de verwerkingsnodes of binnen de aanbiederslimieten, blijft een volgelopen wachtrij extreem lang traag. Zonder een doordacht prioriteitssysteem leiden dergelijke opstoppingen tot een situatie waarin tijdkritische interacties van eindgebruikers geblokkeerd raken door zware, niet-tijdkritische achtergrondprocessen. Het correct ontwerpen van prioriteitswachtrijen is daarom noodzakelijk voor het behoud van systeemintegriteit en werkbare responstijden.
Waarom LLM-verwerking vraagt om een afwijkende wachtrijstrategie
Bij het inrichten van een wachtrijstructuur voor LLM-interacties ontstaat de uitdaging niet alleen door de tijdsduur per aanroep, maar ook door de strikte restricties op de achterliggende capaciteit. Externe LLM-providers hanteren scherpe grenzen voor het aantal gelijktijdige verzoeken (concurrency limits) en de totale hoeveelheid doorgevoerde tokens per minuut (TPM). Zelfs bij het hosten van eigen modellen op toegewezen GPU-clusters is de parallelle verwerkingscapaciteit fysiek beperkt door het beschikbare videogeheugen en het aantal verwerkingseenheden.
Dit betekent dat een applicatie niet onbeperkt extra werknodes kan opstarten om een stijgend aantal verzoeken op te vangen. De beschikbare capaciteit is in feite een schaars, hard begrensd middel. Indien alle verzoeken op een eenvoudige First-In-First-Out (FIFO) basis worden afgehandeld, ontstaat er snel een probleem. Als een geautomatiseerd proces een reeks van honderden documenten instuurt om op te sommen, zal een individuele gebruiker die via een chat-interface een korte vraag stelt achter al die honderden documenten moeten wachten. De gebruiker ervaart een onwerkbare vertraging, terwijl het systeem op maximale capaciteit draait aan taken die net zo goed later uitgevoerd hadden kunnen worden.
Het scheiden van verzoeken is daarom geen optionele optimalisatie, maar een fundamentele randvoorwaarde. Het vereist dat de gateway of de servicelaag de aard van het binnenkomende werk herkent en toewijst aan een passende verwerkingsstroom. Om verzoeken correct op te vangen zonder dat de gateway bezwijkt onder de instroom, is een goede afstemming nodig met rate limiting-mechanismen. Zie hiervoor ook het artikel over het token bucket-algoritme voor LLM-gateways, waarin wordt uitgelegd hoe verzoeksnelheden aan de voordeur worden opgevangen en gereguleerd.
Werksoort als fundament voor prioritisering
Bij de inrichting van prioriteitswachtrijen bestaat de neiging om verzoeken in te delen op basis van de identiteit van de aanvrager, zoals het type klantcontract of de abonnementsvorm. Hoewel een commerciële indeling waardevol kan zijn voor het toewijzen van service level agreements, vormt dit niet de juiste basis voor het technische wachtrijontwerp. Het fundamentele onderscheid in wachtrijarchitectuur hoort gebaseerd te zijn op de werksoort en de daarmee samenhangende wachttolerantie.
In de praktijk laten LLM-taken zich onderverdelen in twee primaire categorieën:
- Interactief werk: Verzoeken waarbij een menselijke gebruiker direct achter een scherm zit te wachten op het resultaat. Voorbeelden zijn een chatbot-reactie, live tekstaanvulling of een interactieve zoekopdracht. De tolerantie voor vertraging is hier extreem laag; een wachttijd van meer dan enkele seconden leidt tot een slechte gebruikerservaring of het voortijdig afbreken van de sessie.
- Achtergrondwerk: Verzoeken die deel uitmaken van een batchproces, asynchrone gegevensverwerking of nachtelijke rapportages. Voorbeelden zijn het indexeren van een kennisbank, de periodieke analyse van klantbeoordelingen of het genereren van offline samenvattingen. Het maakt voor de eindgebruiker of de bedrijfsvoering niet uit of deze taak binnen tien seconden of pas over twee uur is afgerond, mits het werk vóór een bepaalde deadline voltooid is.
Wanneer een organisatie ervoor kiest om prioriteit uitsluitend te koppelen aan klantniveau — bijvoorbeeld door alle verzoeken van een zakelijke klant de hoogste prioriteit te geven — ontstaat er een verstoorde dynamiek. Als die zakelijke klant een zwaar achtergrondproces start met honderdduizenden tokens, blokkeert dat proces het interactieve werk van een minder krachtige gebruiker. Het opsplitsen naar werksoort voorkomt deze botsing. Een zakelijke klant kan binnen deze visie een hogere verwerkingsgarantie krijgen binnen de categorie achtergrondwerk, maar achtergrondwerk mag op de infrastructurele laag nooit zonder meer de interactieve paden van andere gebruikers blokkeren.
Bovendien heeft de keuze van het verwerkende model invloed op de benodigde verwerkingstijd. Een complex redeneermodel vergt meer tijd en capaciteit dan een kleiner, gespecialiseerd model. Het selecteren van de juiste modelgrootte per taak is dan ook een directe partner van de wachtrijstrategie. Lees meer over deze keuzes in de handleiding over het selecteren van een geschikt model per taak.
Het gevaar van verhongering en oplossingen in de praktijk
Het meest hardnekkige probleem bij het toepassen van prioriteit in wachtrijen is verhongering (starvation). Wanneer een systeem gebruikmaakt van een strikte prioriteitsindeling — waarbij klasse 1 altijd volledig wordt afgewerkt voordat klasse 2 aan de beurt komt — kan de laagste klasse oneindig lang blijven steken. Zodra het volume van de hoogste prioriteitsklasse even groot of groter is dan de totale verwerkingscapaciteit van het LLM-cluster, komt de lage prioriteit simpelweg nooit meer aan de beurt.
Belangrijk inzicht: Strikte prioriteit zonder compensatiemechanismen leidt bij continue belasting onvermijdelijk tot de gehele stilstand van lage-prioriteitstaken. Wachtrijontwerp vereist mechanismen die ook de onderste lagen van verwerkingsgaranties voorzien.
Om verhongering te voorkomen, worden in de softwarearchitectuur hoofdzakelijk twee patronen toegepast:
1. Gewogen capaciteitstoewijzing (Weighted Fair Queuing)
Bij deze aanpak wordt de beschikbare verwerkingscapaciteit (uitgedrukt in gelijktijdige verzoeken of tokens per seconde) verdeeld in vaste of dynamische verhoudingen over de verschillende wachtrijen. Denk hierbij aan een verdeling waarbij 70% van de verwerkingscapaciteit gereserveerd is voor interactieve taken, 20% voor standaard API-verzoeken en 10% gegarandeerd beschikbaar blijft voor achtergrondverwerking.
Zelfs wanneer de interactieve wachtrij overloopt en er een enorme piek aan live verzoeken is, blijft die 10% capaciteit gereserveerd voor het achtergrondwerk. Dit voelt op het eerste gezicht contra-intuïtief: waarom zou je capaciteit toewijzen aan een niet-dringende taak terwijl er interactieve gebruikers wachten? De reden is dat achtergrondsystemen vaak afhankelijkheden hebben in de keten. Als achtergrondtaken urenlang nul voortgang boeken, kunnen stroomafwaartse databanken corrupt raken, kunnen geheugenbuffers vollopen of kunnen timeouts in omliggende systemen optreden. Een gegarandeerde minimale doorvoer voorkomt dat de gehele keten instort.
2. Oplopende prioriteit op basis van wachttijd (Priority Aging)
Een alternatieve oplossing is het dynamisch verhogen van de prioriteit naarmate een taak langer in de wachtrij staat. Elk verzoek krijgt bij binnenkomst een basisprioriteit toegewezen op grond van de werksoort. Naarmate de tijd verstrijkt, stijgt de effectieve prioriteit van de taak volgens een vooraf vastgestelde formule.
Een achtergrondtaak die met een lage prioriteit binnenkomt, zal na verloop van tijd een prioriteit bereiken die gelijk is aan die van een nieuw binnenkomende interactieve taak. Hierdoor krijgt de achtergrondtaak uiteindelijk altijd een verwerkingsslot. De uitdaging bij deze aanpak is het correct afstellen van de stijgingssnelheid: stijgt de prioriteit te snel, dan verliezen de hoge-prioriteitsklassen hun voordeel; stijgt deze te langzaam, dan treedt alsnog verhongering op.
| Strategie | Voordeel | Nadeel | Geschikt voor |
|---|---|---|---|
| Strikte Prioriteit | Maximale bescherming van kritiek interactief werk | Groot risico op verhongering van achtergrondwerk | Korte piekbelastingen met lage achtergrondvolumes |
| Gewogen Capaciteit (WFQ) | Gegarandeerde minimale doorvoer voor alle klassen | Interactief werk moet soms wachten bij volle capaciteit | Systemen met continue gemengde werkbelasting |
| Oplopende Prioriteit (Aging) | Voorkomt verhongering zonder harde capaciteitsgrenzen | Complex af te stellen; wachttijden worden minder voorspelbaar | Omgevingen met sterk variërende taakduur |
Begrenzing, verval en afbreken van in-flight verzoeken
Een prioriteitswachtrij die onbeperkt kan groeien, biedt een valse schijn van zekerheid. Het accepteren van verzoeken en deze achteraan een gigantische wachtrij plaatsen, leidt ertoe dat taken pas worden uitgevoerd op een moment dat het resultaat niet langer relevant is. Een robuust systeem stelt daarom strikte grenzen aan de wachtrijlengte en kent een actief vervalbeleid.
Wachtrijbegrenzing en tegendruk (Backpressure)
Wanneer een specifieke prioriteitswachtrij zijn maximale capaciteit heeft bereikt, dient de gateway het verzoek direct te weigeren met een duidelijke foutmelding (zoals de HTTP-statuscode 429 Too Many Requests of 503 Service Unavailable). Dit principe staat bekend als backpressure. Het is voor een aanroepende applicatie veel beter om binnen 10 milliseconden een expliciete weigering te ontvangen dan na 45 minuten wachten alsnog een antwoord te krijgen dat niet meer gebruikt kan worden. De aanroepende zijde kan in dat geval direct overschakelen op een alternatief proces of de gebruiker op de hoogte stellen.
Verval van verzoeken (Time-to-Live)
Naast het begrenzen van de omvang is het essentieel om elk wachtrij-item te voorzien van een maximale levensduur (Time-to-Live of TTL). Veronderstel dat een gebruiker een chatbericht verstuurt, maar na 15 seconden wachten het browsertabblad sluit. Als het verzoek op dat moment nog in de wachtrij staat, heeft het geen enkel nut meer om de LLM-aanroep 30 seconden later alsnog uit te voeren. Dat zou immers kostbare GPU-tijd en tokens opsnoepen voor een antwoord dat nergens meer getoond wordt.
Voordat een worker-node een taak uit de wachtrij oppakt om naar het LLM te sturen, dient de node te controleren of de verstreken tijd de TTL-waarde heeft overschreden. Is dat het geval, dan wordt de taak onmiddellijk gedropt zonder verdere verwerking.
Het afbreken van al lopende verzoeken
Een aspect dat in de praktijk vaak over het hoofd wordt gezien, is de verwerking van annuleringen nadat het verzoek de wachtrij al heeft verlaten en naar de LLM-provider is gestuurd. Als een gebruiker de verbinding verbreekt of een taak annuleert terwijl de LLM de reactie aan het genereren is, blijft de upstream API-aanroep op de achtergrond tokens genereren. Dit veroorzaakt onnodige kosten en bezet verwerkingscapaciteit.
Het wachtrijsysteem en de gateway moeten zo ontworpen zijn dat netwerk-disconnects of annulaties signaalgestuurd worden doorgezet naar de actieve HTTP-verbinding met het taalmodel. Zodra het bronsignaal wegvalt, moet de uitgaande stroom direct worden afgebroken. Voor een gedetailleerde uitwerking van dit mechanisme verwijzen we naar ons artikel over timeouts en cancellation bij LLM-gateways. Bovendien kunnen zware achtergrondprocessen beter worden georganiseerd via gespecialiseerde interfaces; raadpleeg hiervoor het overzicht over batchverwerking via de LLM API.
Gedeelde wachtrijarchitectuur en begrenzing op tempo
In een moderne, geschaalde microservices-architectuur draaien er vrijwel altijd meerdere instanties van de API-gateway en van de achterliggende applicatieservers. Een veelvoorkomende ontwerpfout is het bijhouden van een lokale wachtrij per applicatie-instantie. Hierdoor ontstaat een versnipperd beeld van de werkelijke belasting.
Als instantie A een overvolle lokale interactieve wachtrij heeft, maar instantie B heeft op dat moment nauwelijks interactief werk, kan instantie B beginnen met het verwerken van een lage-prioriteit taak. Ondertussen wachten op instantie A kritieke hoge-prioriteit verzoeken. Het resultaat is dat de globale prioritisering niet meer klopt en afhankelijk wordt van toeval en van de loadbalancer-verdeling.
Een correcte implementatie maakt gebruik van een **centraal gedeelde wachtrijlaag** die toegankelijk is voor alle werknodes. Alle binnenkomende verzoeken worden door de gateways geregistreerd in de centrale wachtrijstructuur. De werknodes die verzoeken doorsturen naar de LLM-providers halen hun taken op uit deze gedeelde bron. Hierdoor is gegarandeerd dat het globaal meest kritieke werk altijd als eerste wordt verwerkt, ongeacht via welke gateway-node het verzoek is binnengekomen.
Hierbij moet de wachtrijstructuur nauw aansluiten op de capaciteitafspraken die met leveranciers of interne beheerders zijn gemaakt. Wanneer prioritisering wordt toegepast zonder dat er een strakke limiet is ingesteld op de uitgaande stroom, zal de wachtrij al het werk te snel doorsturen naar de LLM-provider. De provider zal de verzoeken vervolgens weigeren met foutmeldingen (rate limits), waardoor de prioritisering aan de achterkant alsnog teniet wordt gedaan. Het beheren van verwerkingsgaranties raakt hiermee direct aan de contractuele afspraken over capaciteit; zie hiervoor de toelichting over AI-contracten en SLA-afspraken.
Mocht de capaciteit van een primaire provider onverhoopt volledig uitgeput raken of uitvallen, dan dient het wachtrijsysteem tevens te kunnen terugvallen op alternatieve routes of vereenvoudigde verwerkingsmodi. Dit proces van opvanging bij calamiteiten staat beschreven in het artikel over graceful degradation bij LLM-uitval.
Zichtbaarheid, metrieken en de valkuil van complexiteit
Het beheren van een prioriteitssysteem zonder continue metingen is onmogelijk. Omdat het gedrag van een wachtrij dynamisch verandert bij wisselende werkbelastingen, moeten ontwikkelaars en beheerders direct zicht hebben op het verloop van het systeem.
Essentiële metrieken voor prioriteitswachtrijen
Om te beoordelen of het wachtrijontwerp correct functioneert, zijn de volgende meetwaarden van cruciaal belang:
- Wachttijd per prioriteitsklasse: De tijd die een taak doorbrengt in de wachtrij voordat de verwerking door de LLM daadwerkelijk begint, uitgesplitst naar klasse (bijv. p50, p95 en p99 wachttijden).
- Wachtrijlengte per klasse: Het aantal openstaande taken dat op een gegeven moment in de wachtrij staat per prioriteitsniveau.
- Verhouding geweigerd werk (Rejection Rate): Het percentage verzoeken dat aan de voordeur wordt geweigerd vanwege een volle wachtrij (backpressure).
- Verhouding vervallen werk (Drop Rate): Het aantal taken dat is verlopen als gevolg van het overschrijden van de ingestelde TTL-waarde.
- In-flight annuleringen: Het aantal actieve LLM-aanroepen dat voortijdig is afgebroken vanwege het wegvallen van de clientverbinding.
Voor een breder overzicht van de telemetrie en monitoring die nodig is rondom AI-infrastructuur, verwijzen we naar het artikel over observability en logging bij LLM-applicaties.
De valkuil van te veel prioriteitsklassen
Een veelgemaakte fout bij het inrichten van prioriteitsontwerpen is het introduceren van te veel fijnmazige klassen. Het lijkt aantrekkelijk om onderscheid te maken tussen "Kritiek", "Hoog", "Normaal-Hoog", "Normaal", "Laag", "Achtergrond-Snel" en "Achtergrond-Traag". In de praktijk blijkt een dergelijke uitgebreide indeling vrijwel onbeheersbaar.
Hoe meer klassen er zijn, hoe moeilijker het wordt om het gedrag onder zware belasting te voorspellen. Het afstellen van gewichten of stijgingssnelheden wordt een doolhof van afhankelijkheden. Bovendien weten ontwikkelaars binnen een organisatie op een gegeven moment niet meer welke klasse zij moeten selecteren voor een nieuwe functionaliteit, wat ertoe leidt dat iedereen uit voorzorg kiest voor een van de hoogste klassen. Hierdoor devalueert de prioritisering en vervalt het systeem in feite weer tot een ongestructureerde massa.
In de praktijk volstaan **drie heldere klassen** voor het overgrote deel van de toepassingen:
- Interactief (Prioriteit 1): Rechtstreekse menselijke interactie waar een antwoord binnen enkele seconden verwacht wordt.
- Standaard / Asynchroon (Prioriteit 2): Geautomatiseerde processen die direct resultaat vereisen voor een workflow, maar waarbij de gebruiker niet actief op het scherm zit te turen.
- Achtergrond / Batch (Prioriteit 3): Grote gegevensvolumes, periodieke indexeringen en nachtelijke verwerking zonder harde tijdsdruk op de korte termijn.
Door deze driedeling strak te hanteren en te combineren met gewogen capaciteitstoewijzing, strikte begrenzing en transparante metrieken, blijft de LLM-infrastructuur voorspelbaar, stabiel en kostenefficiënt — zelfs tijdens onverwachte belastingpieken.
Lees ook
Voor verdere verdieping in het bouwen van schaalbare en betrouwbare LLM-infrastructuur adviseren wij de volgende artikelen:
- Token Bucket Algoritme voor LLM Gateways — Snelheidsbegrenzing en verkeersregulering aan de voordeur van de API.
- Batchverwerking via de LLM API — Efficient omgaan met grote volumes asynchrone taken.
- Timeouts en Cancellation bij LLM Interfaces — Voorkomen van onnodig tokenverbuik bij afgebroken sessies.
- Graceful Degradation bij LLM Uitval — Strategieën om de dienstverlening overeind te houden bij leveranciersstoringen.
- Observability en Logging — Inzicht in prestatiestatistieken, wachtrijen en foutpercentages.
- Het Juiste Model per Taak Selecteren — Optimalisatie van capaciteit en kosten door gerichte modelkeuze.
- AI-Contracten en SLA-Afspraken — Juridische en operationele waarborgen rondom verwerkingscapaciteit.

