Simulating AWS & Azure Failures Without Running AWS or Azure

How to use LocalStack, Moto, and Azurite to test cloud failure scenarios without cloud costs.

You don’t need a $10,000/month cloud bill to test cloud failure scenarios. Local emulators can simulate most failures that actually cause production incidents — and the tooling has matured dramatically.

350M+

Docker pulls (Dec 2025)

70+

Emulated by LocalStack

$2.36B

Market size 2025

57%

Azure Dev/Test discount

The Emulator Landscape

Cloud emulation has become a critical part of the modern development stack. LocalStack raised $25M in Series A funding in November 2024, with backing from major players who recognize that testing against real cloud services doesn’t scale. At AWS re:Invent 2025, the company announced record adoption with over 1,500 customers including Apple, Comcast, IBM, and Workday.

Cloud ProviderEmulation ToolBest For
AWSLocalStackMost complete AWS emulation (70+ services)
AWS (Python)MotoUnit test mocking with decorators
Azure StorageAzuriteBlob, Queue, and Table storage
Azure Cosmos DBCosmos DB EmulatorFull Cosmos API locally
GCPCloud SDK emulatorsPub/Sub, Datastore, Firestore

LocalStack: Your Local AWS

LocalStack has become the de facto standard for local AWS development. It runs as a Docker container and exposes a single endpoint that handles requests for all emulated services.

Quick Start

# Start LocalStack
docker run -d \
  --name localstack \
  -p 4566:4566 \
  -e SERVICES=s3,dynamodb,sqs,lambda \
  localstack/localstack

# Configure AWS CLI
aws configure set aws_access_key_id test
aws configure set aws_secret_access_key test

# Create S3 bucket locally
aws --endpoint-url=http://localhost:4566 s3 mb s3://my-bucket

# Upload a file
aws --endpoint-url=http://localhost:4566 s3 cp file.txt s3://my-bucket/

Service Coverage

LocalStack’s coverage has expanded significantly. The community edition handles the core services most applications need, while the Pro edition adds advanced features like IAM enforcement, Lambda layers, and fault injection.

Emulation QualityServicesNotes
Fully emulatedS3, DynamoDB, SQS, SNS, Lambda, KinesisComplete API coverage including streams and transactions
Partially emulatedEC2, RDS, ECSMetadata and lifecycle, but no actual compute
Pro-onlyIAM enforcement, Cognito, API GatewayRequires LocalStack Pro license

LocalStack Pro Fault Injection

LocalStack Pro includes a fault injection API that lets you simulate specific AWS errors on demand. You can configure S3 to return 503 errors for 50% of GetObject requests, or DynamoDB to throw ProvisionedThroughputExceededException — without writing wrapper code.

Injecting Failures with LocalStack

The real value of local emulation is testing how your application handles failures. LocalStack Pro’s fault injection API makes this straightforward:

import boto3
from localstack_client.config import get_service_endpoint

# Configure client
s3 = boto3.client(
    's3',
    endpoint_url=get_service_endpoint('s3'),
    aws_access_key_id='test',
    aws_secret_access_key='test'
)

# LocalStack Pro: Inject errors
# This returns 503 for 50% of requests
localstack.inject_fault(
    service='s3',
    operation='GetObject',
    error_code=503,
    probability=0.5
)

# Test your application's handling
try:
    response = s3.get_object(Bucket='my-bucket', Key='file.txt')
except ClientError as e:
    if e.response['Error']['Code'] == '503':
        handle_throttling()

For DynamoDB, you can simulate the infamous ProvisionedThroughputExceededException that catches many teams off guard in production:

# Simulate DynamoDB throttling
localstack.inject_fault(
    service='dynamodb',
    operation='PutItem',
    error_code='ProvisionedThroughputExceededException',
    probability=0.3
)

This lets you verify that your retry logic with exponential backoff actually works before you hit real throttling in production.

Moto: Python AWS Mocking

For unit tests where you want complete isolation, Moto provides decorator-based mocking that’s cleaner than LocalStack for simple cases:

import boto3
from moto import mock_s3
import pytest

@mock_s3
def test_s3_operations():
    # Moto creates mock AWS environment
    s3 = boto3.client('s3', region_name='us-east-1')
    s3.create_bucket(Bucket='test-bucket')

    # Your code under test
    s3.put_object(Bucket='test-bucket', Key='test.txt', Body=b'hello')

    # Assertions
    response = s3.get_object(Bucket='test-bucket', Key='test.txt')
    assert response['Body'].read() == b'hello'

The trade-off: Moto is faster and simpler for unit tests, but LocalStack provides higher fidelity for integration tests where you need realistic API behavior.

Azurite: Local Azure Storage

For Azure, Azurite is the official Microsoft storage emulator, supporting Blob, Queue, and Table storage:

# Start Azurite
docker run -d \
  -p 10000:10000 \
  -p 10001:10001 \
  -p 10002:10002 \
  mcr.microsoft.com/azure-storage/azurite

# Configure connection string
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=<key>;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"

# Create container
az storage container create --name mycontainer

Azure Emulation Gaps

Unlike LocalStack’s broad coverage of AWS, Azure emulation is more fragmented. Azurite covers storage, but you’ll need separate emulators for Cosmos DB, Service Bus, and other services. LocalStack announced Azure support in 2024, currently in alpha, which may eventually provide a more unified experience.

What Can and Cannot Be Simulated

Understanding the limits of local emulation is crucial. Some failures can be tested with high fidelity locally; others require real cloud infrastructure.

Fidelity LevelWhat You Can TestLimitations
High fidelityAPI error codes (429, 503), authentication failures, response format validationActual timing and ordering may differ
Medium fidelityArtificial latency injection, partial failure rates, service unavailabilityNot real network behavior
Cannot simulateReal network partitions, actual capacity limits, cross-region replication lag, IAM propagation timingRequires real cloud or advanced chaos tools

The key insight: local emulation excels at testing your application’s response to failures. It’s less suited for discovering new failure modes that emerge only at scale.

Building a Test Suite

A practical approach layers different testing strategies:

Unit tests with Moto: Fast, isolated tests for individual functions that interact with AWS. Run on every commit.

Integration tests with LocalStack: Slower tests that verify complete workflows. Run in CI/CD pipeline with LocalStack as a service container.

Staging tests with real cloud: Reduced-scale real infrastructure. Catches issues that emulation misses.

# .github/workflows/test.yml
name: Test Cloud Failure Handling

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      localstack:
        image: localstack/localstack
        ports:
          - 4566:4566

    steps:
      - uses: actions/checkout@v4

      - name: Run failure tests
        env:
          AWS_ENDPOINT_URL: http://localhost:4566
        run: |
          pytest tests/cloud_failures/

Demo Credibility vs. Production Fidelity

There’s an important distinction between what demos need and what production testing requires.

For demos and developer testing: Local emulation is excellent. You get realistic API responses, reproducible failure scenarios, and the ability to show detection and remediation without cloud costs. The error formats match real AWS/Azure, and timing is configurable.

For production resilience: Local emulation has limits. Real capacity constraints, network partitions, multi-region replication lag, and cascading failures across services don’t behave the same locally. That’s where chaos engineering tools like Gremlin, LitmusChaos, or Azure Chaos Studio come in — a market projected to reach $3.51 billion by 2030.

The Right Tool for Each Stage

Development and unit testing: Use Moto for speed. Integration testing: Use LocalStack for fidelity. Staging: Use real cloud at reduced scale. Production validation: Use controlled chaos engineering with proper safeguards.

The Cost Equation

According to Azure pricing analysis, running a development VM costs roughly $75/month. Multiply that by your team size, add database instances, and cloud development costs add up fast. Azure offers dev/test pricing with up to 57% discount for Visual Studio subscribers.

But local emulation costs nothing. LocalStack’s community edition is free. Your CI/CD runs don’t incur cloud charges. Developers can test failure scenarios without spinning up expensive infrastructure.

The math is straightforward: local emulation for development and testing, real cloud only when you need the fidelity that emulation can’t provide.

References


This is part 2 of our “Cloud Failures Without the Cloud” series.