← Azure Failure Labs
05 / 12 Technical field note

When the Thing You Call Breaks: The Dependency Lab

How a dependency failure lab shows that an application is only as healthy as the downstream call it relies on.

AzureDependenciesChaos EngineeringMonitoring

Your application is only as healthy as the weakest service it calls. The deploy is green, the code is fine, the instance is up, and users are still seeing errors, because something downstream is timing out or returning garbage. The dependency lab recreates that situation: the primary app stays deployed and online while a service it relies on is stopped, slowed, or forced to return errors.

What the lab does

It runs a primary App Service that depends on a secondary stub service on the same shared plan. The Logic App controller breaks the stub in three ways while the primary app stays exactly where it was. The interesting failure here is not the primary going down, it is the primary going unhealthy without changing at all.

flowchart LR OP["Operator"] -->|"scenario"| LA["Logic App\ndependency-controller"] LA -->|"stop / latency / 503"| STUB["Dependency stub"] MAIN["Primary app"] -->|"calls"| STUB MAIN --> MON["Azure Monitor"] MON --> AG["Shared action group"] OP -.->|"recover"| LA

The inject contract

{ "scenario": "dependency-503", "durationSeconds": 300 }

The scenarios are dependency-stop (the stub goes away entirely), dependency-latency (the stub answers slowly, with a configurable delay), dependency-503 (the stub returns service-unavailable), and recover. Each one breaks the call in a different way, and they surface differently in the primary app’s telemetry, which is the point.

From POST to symptom

sequenceDiagram participant Op as Operator participant LA as Logic App participant STUB as Dependency stub participant MAIN as Primary app participant M as Azure Monitor Op->>LA: POST dependency-503 LA->>STUB: Force 503 responses MAIN->>STUB: Downstream call STUB-->>MAIN: 503 MAIN-->>M: Primary 5xx and latency rise Note over MAIN: Primary never redeployed Op->>LA: POST recover LA->>STUB: Healthy responses restored

The signal that proves it

The alert watches the primary app’s 5xx, not the stub’s. That is deliberate. You want to catch the failure where your users feel it.

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

The dependency-latency scenario shows up as rising response time on the primary rather than 5xx, which is a useful contrast to demonstrate: a slow dependency and a broken dependency produce different curves, and your responders should learn to read both.

Recovery

recover returns the stub to healthy responses. The primary app’s calls succeed again, its 5xx drops, and its latency settles. Baseline is the primary returning 200 with normal response time, no changes ever having been made to the primary itself.

The lesson

Monitor the caller, not just the callee. It is tempting to put your alerting on the dependency and call it done, but the dependency is not what your users touch. When the stub returns 503, the symptom that matters is the primary app’s error rate, because that is the experience on the other side of the screen. Watching the primary also catches a whole class of failures the dependency’s own health checks miss, including the dependency being completely gone, which a stopped service cannot report on its own behalf.


Next: The Secret That Vanished, the auth and Key Vault lab.

Architecture depth + engineering leadership

Building platforms enterprises trust at scale.