← Azure Failure Labs
04 / 12 Technical field note

Deterministic Application Failure: The App Service Lab

How to inject deterministic 500s, exceptions, and latency into App Service so application failure can be rehearsed and recovered on demand.

AzureApp ServiceChaos EngineeringReliability

There is a particular kind of demo that falls flat: you trigger a failure, the dashboard shows one sad red dot, and then nothing, because a single failing request does not move a chart built for production traffic. The App Service lab solves that by making failure both deterministic and busy. It can push an app into 500s, exceptions, latency, or a full stop, and it generates enough sustained traffic that the telemetry actually moves while the fault is live.

What the lab does

It deploys a small Python web app instrumented with Azure Monitor OpenTelemetry, plus a Logic App controller that flips the app between failure modes. The app keeps /healthz returning 200 even during injected failures, on purpose, so App Service health checks do not quietly recycle the instance and erase the scenario you are trying to show. It also exposes an admin load endpoint so the controller can drive continuous traffic during a drill.

flowchart LR OP["Operator"] -->|"scenario + load params"| LA["Logic App\nwisdm-app-failure-controller"] LA -->|"set failure mode"| APP["App Service\nfailure target"] LA -->|"/admin/load"| APP APP --> AI["Application Insights\nLive Metrics"] APP --> MON["Azure Monitor"] MON --> AG["Shared action group"] OP -.->|"scenario: recover"| LA

The inject contract

The payload names the scenario and shapes the load. The load fields are what keep the charts populated instead of catching one lonely request.

{
  "scenario": "http500",
  "durationSeconds": 300,
  "burstRequests": 120,
  "loadDurationSeconds": 300,
  "loadConcurrency": 8,
  "loadIntervalMs": 100
}

The scenarios are http500, exception, latency, stop, and recover. For http500 and exception, the controller fires an initial burst and then keeps continuous foreground load running, so Live Metrics stays busy. For latency, it starts traffic right after enabling the delay, so the response-time graph moves without anyone manually clicking around.

From POST to alert

sequenceDiagram participant Op as Operator participant LA as Logic App participant APP as App Service participant AI as App Insights participant M as Azure Monitor Op->>LA: POST scenario http500 LA->>APP: Enable 500 mode LA->>APP: Drive burst + sustained load APP-->>AI: 5xx and request volume climb APP-->>M: Http5xx metric rises M->>M: Scheduled query 5xx count over threshold Note over APP: /healthz stays 200 throughout Op->>LA: POST recover LA->>APP: Normal mode, traffic settles

The signal that proves it

A scheduled-query alert counts 5xx responses from the app’s HTTP logs and fires past a small threshold.

AppServiceHTTPLogs
| where TimeGenerated > ago(5m)
| where _ResourceId =~ "<webapp-resource-id>"
| where ScStatus >= 500
| summarize FailureCount = count() by _ResourceId
| where FailureCount > 5

A second activity-log alert catches the stop scenario specifically, because a stopped app produces a different shape of failure than one returning 500s, and you want to tell them apart at a glance.

The latency scenario does not raise 5xx at all. It pushes AverageResponseTime up instead, and the sustained load is what keeps the duration chart readable while the delay is active.

Recovery

recover returns the app to normal request behavior and lets traffic settle. Baseline is a 200 on the app root, /healthz still green (it never left), 5xx counts back to zero, and response time back to its normal band.

The lesson

A failure demo is only as convincing as the telemetry behind it, and production telemetry is built to ignore single events. If you want a drill that teaches something, you have to generate enough load that the signal rises above noise, and you have to keep your health endpoint honest so the platform does not paper over the failure for you. The design choice to hold /healthz at 200 during a fault looks counterintuitive until you have watched App Service silently recycle an instance mid-demo and wipe out the exact symptom you were trying to show a room full of people.


Next: When the Thing You Call Breaks, the dependency lab.

Architecture depth + engineering leadership

Building platforms enterprises trust at scale.