Durable execution
Wat is durable execution?
Durable execution draait een proces zo dat het overleeft wat er ook met de machines eronder gebeurt. De run duurt drie minuten of drie weken, een server kan halverwege crashen, en je kan uitrollen terwijl hij staat te wachten. Hij gaat verder waar hij gestopt was, in plaats van opnieuw te beginnen of stilletjes te verdwijnen.
Restate, een van de engines in deze categorie, noemt het een programmeerparadigma dat gewone code bestand maakt tegen crashes, herstarts en fouten in de infrastructuur. Temporal formuleert dezelfde belofte als een garantie dat je toepassing tot het einde doorloopt.
Drie doodgewone situaties leggen uit waarom iemand daar moeite voor doet.
Wat drie dagen wacht op de goedkeuring van een zaakvoerder, kan niet in een variabele in het geheugen leven.
Een betaalstap loopt in timeout. Je weet niet of het geld vertrokken is, dus de tweede poging moet weten dat die stap al gedraaid heeft.
Er gaat een release uit terwijl veertig processen halfweg staan. Elke worker herstart, en die veertig runs moeten er daarna nog altijd zijn.
Het verschil met een workflow die je in een designer tekent: het proces blijft gewone code. Roep een stap aan, wacht drie dagen, roep de volgende stap aan. De engine zorgt dat die functie blijft leven.
Hoe de engine onthoudt waar hij stond
Elke stap gaat naar een duurzame log voordat het resultaat bij je functie terugkomt. Restate zegt het rechtuit: elke betekenisvolle stap, een externe API-call, een wegschrijving naar de databank, een sleep, een bericht naar een andere dienst, wordt naar een blijvende log geschreven voordat het resultaat teruggegeven wordt. Temporal noemt zijn versie de Event History, een volledige en duurzame log van alles wat er in een workflow gebeurd is.
Herstel gebeurt via replay, en de documentatie van Microsoft over Durable Task legt uit wat dat betekent. Zodra er weer werk is, wordt de orkestrator wakker en voert hij de hele functie opnieuw uit vanaf het begin om de lokale toestand op te bouwen. Telkens de code een stap bereikt, kijkt het framework in de historiek, en een stap die daar al een resultaat heeft, geeft dat meteen terug. Bij het eerste dat nog niet gebeurd is, stopt de replay en draait de code echt.
Je lokale variabelen worden nergens bewaard. Ze worden heropgebouwd door dezelfde code opnieuw te draaien over antwoorden die al vastliggen. Daardoor valt het programma in twee: workflowcode, die opnieuw afgespeeld wordt en enkel mag beslissen, en activities, die de buitenwereld een keer raken en hun resultaat in de log zetten.
Met de toestand in de engine zijn er vier dingen die je niet meer zelf schrijft. Wachten in dagen: Temporal zegt dat een workflow maanden kan slapen, en de bewaarde timer loopt alsnog af zodra de worker terug is. Wachten op een signaal van buiten, wat Azure een external event noemt en AWS Step Functions een callback met een task token. Een retry-regel per stap. En een volledige historiek, die volgens Microsoft ook betrouwbare compenserende acties mogelijk maakt wanneer een latere stap faalt.
De regels die bij replay horen
Replay is waar ontwikkelaars zich vergissen, want het beperkt wat workflowcode mag doen. Microsoft zegt het zonder omwegen: een orkestrator wordt meerdere keren opnieuw afgespeeld en moet elke keer hetzelfde resultaat geven.
In workflowcode vallen deze dingen dus af.
De klok.
DateTime.Nowgeeft bij elke replay een andere waarde. Gebruik de tijd van de context zelf.Toevalsgetallen en verse GUIDs. Gebruik de replay-veilige generator van de context, of haal de waarde uit een opgeslagen stap.
Rechtstreekse netwerk- en databankoproepen. Microsoft schrijft dat orkestrators zelf nooit rechtstreekse HTTP-calls doen, omdat replay dan dubbele I/O veroorzaakt. Durable Functions heeft daarvoor een eigen durable HTTP-API, waar de oproep wel mee in de historiek gaat. Temporal zegt hetzelfde over API-calls, databankqueries en model-oproepen: die horen in activities.
De thread laten slapen.
time.sleepblokkeert echt een worker. Gebruik de duurzame timer van de engine.Omgevings- en statische variabelen. Allebei kunnen ze veranderen tussen de run en een replay twee dagen later. Geef configuratie mee als input.
Overtreed je de regel, dan faalt het luid. Temporal geeft een non-determinisme-fout wanneer een commando uit de replay niet strookt met de event history, en het Durable Task Framework gooit een NonDeterministicOrchestrationException, al waarschuwt Microsoft dat die detectie niet alles vangt. Het regelboek past in vier woorden: workflowcode beslist, activities doen.
Een goedkeuring van drie dagen die een release overleeft
Neem een bestelbon boven 5.000 euro die een handtekening van de zaakvoerder nodig heeft.
Maandag 09:12. De run valideert de bestelbon, reserveert het budget in het ERP als reservatie R-4417, en stuurt de goedkeuringsmail. Drie resultaten in de log.
Maandag 09:13. Hij komt aan de lijn die wacht op een goedkeuring of op drie dagen. Er staat nu niets meer in het geheugen. De engine houdt een timer bij die donderdag om 09:13 afloopt, en een open wachtpunt voor een event met de naam goedkeuring.
Dinsdag 14:00. Je rolt een release uit en elk workerproces herstart. De run blijft ongemoeid, want er zat niets in een proces dat verloren kon gaan.
Woensdag 08:40. De zaakvoerder klikt op goedkeuren. Een worker speelt de run opnieuw af: de validatie, R-4417 en de mailstap geven alle drie hun opgeslagen resultaat terug, en het wachtpunt heeft nu een antwoord.
De replay komt bij het boeken van de bestelling, het eerste dat nog nooit gebeurd is, en voert dat echt uit. De goedkeuringsmail is precies een keer vertrokken.
Verander een detail en het loopt fout. Had de release van dinsdag een extra meldingsstap tussen de budgetreservatie en de mail gezet, dan kwam de replay van woensdag bij een oproep die niet in de historiek staat, en faalde de run met een non-determinisme-fout. Microsoft benoemt de oorzaken: de naam, het inputtype of het outputtype van een activity wijzigen, en oproepen naar activities, timers of external events toevoegen, weghalen of van volgorde veranderen. Zoiets zonder plan uitrollen levert gefaalde runs op, of runs die voor eeuwig op running blijven staan. De uitwegen zijn orchestration versioning, een side-by-side uitrol op een eigen task hub, of de lopende runs bewust stopzetten.
Durable execution versus een retry op een gewone job
Allebei antwoorden ze op dezelfde klacht: de job is gefaald, draai hem opnieuw. Ze verschillen op een punt, namelijk wat er tussen twee pogingen onthouden wordt.
Een retry op een gewone job onthoudt niets. De tweede poging begint bij regel een met een leeg geheugen, dus alles wat de eerste poging al aan de buitenwereld gedaan heeft, gebeurt opnieuw, tenzij je de bescherming zelf gebouwd hebt: een idempotency key, een tabel met verwerkte records, een statuskolom die je voor elke stap nakijkt.
Durable execution onthoudt elke afgewerkte stap. De retry speelt die resultaten opnieuw af en doet pas echt werk vanaf de eerste stap die nooit afgeraakt is. De mail vertrekt geen tweede keer, omdat het versturen geen tweede keer uitgevoerd wordt.
Een gewone retry past bij een korte job die je veilig van boven af opnieuw kan draaien, zoals een nachtelijke laadbeurt naar een stagingtabel die je eerst leegmaakt. Idempotentie wordt in geen van beide gevallen overbodig: een stap kan in timeout gaan nadat de andere kant al bevestigd heeft, en de engine ziet geen resultaat en probeert opnieuw.
Een agent-run heeft dezelfde vorm
Een run van een AI-agent is hetzelfde probleem, en daarom zijn de leveranciers van durable execution ook op die markt gesprongen. De engineering-post van Restate zegt het simpel: een agent is gewoon code, een loop die context verzamelt, tools of een model aanroept, uitzoekt wat er nu moet gebeuren, en dat herhaalt. Elke tool-call is een sprong over het netwerk, elke tussenkomst van een gebruiker is een pauze, elke retry riskeert hetzelfde werk twee keer te doen, en een netwerkprobleem alleen al kan alles wegvegen wat de run opgebouwd heeft.
Een model-oproep die veertig seconden duurt en geld kost, is de laatste stap die je wil herhalen omdat een container gerecycleerd werd. Dus schrijven de frameworks model-oproepen en tool-calls in een journaal en spelen ze terug tot de laatste afgewerkte stap. Gehoste agent-runtimes beschrijven hun sessies in dezelfde termen. De regel over determinisme geldt hier ook, met een kanttekening: een model-oproep is het minst voorspelbare stuk van je systeem, en net daarom hoort ze in een opgeslagen stap en nooit in code die opnieuw afgespeeld wordt.
Waar moet je op letten bij durable execution
Je hebt Temporal waarschijnlijk niet nodig. De meeste bedrijven draaien hun processen in Power Automate, Logic Apps of de workflowmodule van hun ERP, en daar zit al een duurzame engine onder. Je moet de term kennen om te kunnen benoemen wat er misging toen er vorige maand een dossier verdween, niet om te gaan winkelen.
Ken de plafonds van je platform. Een cloud flow in Power Automate heeft een maximale looptijd van 30 dagen vanaf de start van de run, openstaande goedkeuringen inbegrepen, en daarna gaat elke openstaande stap in timeout. De historiek van runs blijft ook 30 dagen bewaard. Een goedkeuring waar vijf weken niemand aan geraakt heeft, faalt dus niet luid: ze verloopt, en een maand later is het bewijs ook weg.
Behandel proces-code als een databankschema. Er zitten levende instanties in, dus een wijziging aan de volgorde van de stappen vraagt evenveel plan als het hernoemen van een kolom.
In de log staat klantendata. De input en de output van elke stap gaan naar duurzame opslag, dus namen, bedragen en mailteksten komen daarin terecht. Kijk na hoe lang die historiek bewaard blijft en wie ze mag lezen.