När vi nyligen skulle modernisera en lösning byggd på AWS Fargate stötte vi på flera oväntade utmaningar som blev värdefulla lärdomar kring skalning, nätverk och begränsningar i AWS Batch.
Lösningen i sig är relativt enkel: varje testfall körs i en egen container i Fargate och resultatet skrivs sedan till S3. Målet var att ersätta vår egen orkestrering med AWS Batch för att minska mängden egen kod och få inbyggt stöd för exempelvis timeout-hantering.
Det visade sig dock snabbt att AWS Batch fungerar annorlunda jämfört med "vanlig" Fargate.
Ett av de första problemen vi stötte på handlade om ephemeral ports. Våra containrar behövde öppna portar som redan användes av andra processer, vilket skapade konflikter. I vanlig Fargate går detta att lösa genom att sätta systemControls i task-definitionen och justera intervallet för lokala portar.
"systemControls": [
{
"namespace": "net.ipv4.ip_local_port_range",
"value": "20000 40000"
}
]Den möjligheten saknades däremot i vår Batch-konfiguration, vilket gjorde migreringen betydligt mer komplex än väntat.
En annan anledning till att vi ville använda AWS Batch var dess "fire-and-forget"-modell samt inbyggda stöd för timeout på jobb. Batch accepterar jobb oavsett om underliggande nätverkskapacitet faktiskt räcker till eller inte, vilket innebär att man själv behöver dimensionera sina subnet korrekt för den maximala mängd samtidiga jobb man planerar att köra.
{
"timeout": {
"attemptDurationSeconds": 3600
}
}Här blev en viktig lärdom att subnet måste dimensioneras generöst. Även om Batch accepterar jobben betyder det inte att infrastrukturen klarar att exekvera dem stabilt.
Det största problemet dök dock upp först vid hög belastning. När vi började köra över 1000 containrar samtidigt försvann jobb "mystiskt". Inga resultat skrevs till S3 och det fanns få ledtrådar till vad som egentligen gick fel.
Till slut byggde vi en alternativ lösning där vi själva orkestrerade Batch-liknande funktionalitet ovanpå vanlig Fargate. Först då fick vi ett tydligt felmeddelande i loggarna:
2026-04-30 14:00:28,842 - __main__ - ERROR - run_task failure: arn=None reason=You've reached the limit on the number of vCPUs you can run concurrently detail=NoneProblemet handlade alltså inte om subnet eller nätverk – utan om AWS-kontots vCPU-begränsningar. Ett ganska viktigt felmeddelande som vi önskar att Batch hade exponerat tydligare från början.
När vi gick tillbaka till vanlig Fargate kunde vi återigen använda systemControls för att hantera ephemeral ports. Däremot förlorade vi Batch-funktionaliteten för timeout. Lösningen blev därför att implementera timeout direkt i containerns CMD med Linux timeout.
CMD ["/bin/bash", "--login", "-c", "timeout -k 60 1800 /usr/local/bin/script.sh"]Det visade sig vara en väldigt praktisk lösning. Utan timeout kan hundratals eller tusentals hängande containrar snabbt bli en dyr historia – särskilt över en helg.
En stor fördel med denna approach är också att processen får möjlighet att fånga SIGINT innan containern termineras. Det gör det möjligt att exempelvis ladda upp loggar eller mockade testresultat till S3 innan jobbet avslutas, vilket förenklar felsökning avsevärt.
Sammanfattningsvis blev projektet en tydlig påminnelse om att AWS Batch inte alltid är ett "drop-in replacement" för Fargate. Vid hög skala behöver man förstå begränsningar kring nätverk, ephemeral ports och framför allt konto-specifika vCPU-limiter. I vårt fall visade det sig att en enklare egen orkestrering ovanpå vanlig Fargate gav både bättre kontroll och bättre observability.
