Cold starts in Azure Functions — what they are and how to mitigate
A cold start happens when Azure has to allocate a new function instance from scratch — typically because (a) no instance is running, or (b) load just spiked and a new instance was needed. The first invocation pays the platform setup cost.
What happens during a cold start
1. Azure allocates a worker VM (~50-200 ms)
2. Mounts your function app (~100-500 ms)
3. Starts the language host (~100-300 ms)
4. JIT-compiles your assemblies (~500-2000 ms, .NET)
5. Runs static initializers + DI setup (~100-1000 ms, depends on app)
6. Runs your function code (variable)
Total for .NET on Consumption: 1-5 seconds, dominated by JIT + DI setup.
How cold starts compare across languages
| Runtime | Typical cold start |
|---|---|
| Node.js | 500 ms – 2 s |
| Python | 500 ms – 2 s |
| .NET 8+ isolated worker | 1 – 3 s |
| .NET 8+ AOT (Native AOT) | 200 – 800 ms |
| Java | 3 – 10 s (worst) |
When you DON'T pay cold start
- Subsequent invocations within ~10-20 min of the previous one — the instance stays warm
- All invocations on Premium plan (instances are pre-warmed)
- All invocations on App Service Plan (always running)
Mitigation strategies
1. Move to Premium or Flex Consumption
The most reliable fix. Premium pre-warms instances; Flex Consumption has much faster cold starts than legacy Consumption.
resource plan 'Microsoft.Web/serverfarms@2023-12-01' = {
name: 'plan-functions'
sku: { name: 'EP1', tier: 'ElasticPremium' }
properties: { maximumElasticWorkerCount: 20 }
}
2. Use .NET 8+ Native AOT
.NET Native AOT removes the JIT step entirely. Cold start drops from 1-5 s to 200-800 ms.
<!-- .csproj -->
<PropertyGroup>
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
Limitations: no reflection-heavy libraries, code must be AOT-compatible.
3. Reduce app size and dependencies
- Each NuGet package adds startup time
- Use
PublishTrimmed=trueto strip unused code - Move heavy initialization OUT of static constructors and DI registration
// ❌ Runs on cold start, even for unrelated functions
public class HeavyService {
static HeavyService() {
BuildExpensiveLookupTable(); // 800 ms
}
}
// ✅ Lazy — only runs when the service is actually used
public class HeavyService {
private static readonly Lazy<LookupTable> _table = new(BuildExpensiveLookupTable);
}
4. Health-check ping ("keep-warm")
Schedule a Timer function that hits your HTTP function every 5 minutes. The instance stays warm.
[Function("KeepWarm")]
public async Task KeepWarmAsync(
[TimerTrigger("0 */5 * * * *")] TimerInfo timer,
[HttpClientFactory] HttpClient http)
{
await http.GetAsync("https://myapp.azurewebsites.net/api/health");
}
Cheap on Consumption (small executions), works well for low-traffic apps that occasionally get a critical user request.
5. Use AlwaysReady instances on Flex Consumption
Flex Consumption lets you set a minimum number of always-ready instances per function. Best of both worlds: scale to zero for cold paths, never cold-start for the hot path.
"functionAppConfig": {
"scaleAndConcurrency": {
"alwaysReady": [
{ "name": "PaymentHandler", "instanceCount": 1 }
]
}
}
When cold start doesn't matter
- Webhook receivers (the caller doesn't notice a 2 s response)
- Background queue processors (a 2 s startup adds to ALL processing, but throughput is what matters)
- Scheduled jobs (no user waits)
- Internal automation
When cold start is unacceptable
- User-facing API where p95 latency must be < 500 ms
- Real-time chatbot responses
- Financial transaction APIs with hard SLAs
For these, you should NOT be on Consumption. Move to Premium or use Web API on App Service.
Common interview follow-up
"Our webhook is on Consumption, occasionally gets a 5 s response. Stripe is complaining. What's the cheapest fix?"
Tiered answer:
- Cheapest: add a Timer keep-warm pinging the webhook every 5 min (~₹50/month extra)
- Better: migrate to Flex Consumption (~5x reduction in cold start, similar cost)
- Best: Premium EP1 with always-ready=1 (no cold start, but ~₹10,000/month)
Pick based on how often the cold start actually fires. If it's once a day at 3 AM, keep-warm; if it's during business hours, Flex or Premium.