LocalStack Development¶
LocalStack provides a local AWS environment for development and testing. This guide covers setting up zae-limiter with LocalStack.
Why LocalStack?¶
- Free - No AWS costs during development
- Fast - No network latency
- Isolated - No risk to production data
- Full stack - DynamoDB, Lambda, Streams, CloudFormation
Quick Start¶
1. Start LocalStack¶
The zae-limiter local commands are the source of truth for LocalStack container configuration:
# Start LocalStack
zae-limiter local up
# Start and show deploy instructions
zae-limiter local up --name my-app
# Check status
zae-limiter local status
# View logs
zae-limiter local logs --follow
# Stop
zae-limiter local down
See CLI Reference for full options.
The project includes a pre-configured docker-compose.yml at the repository root:
docker run -d \
--name zae-limiter-localstack \
-p 4566:4566 \
-e SERVICES=dynamodb,dynamodbstreams,lambda,cloudformation,logs,iam,cloudwatch,sqs,s3,sts,resourcegroupstaggingapi \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "${TMPDIR:-/tmp}/localstack:/var/lib/localstack" \
localstack/localstack:4.14
Docker Socket Required
The Docker socket mount (-v /var/run/docker.sock:/var/run/docker.sock) is required for LocalStack to spawn Lambda functions as Docker containers.
2. Deploy Infrastructure¶
3. Use in Code¶
from zae_limiter import RateLimiter, Limit
limiter = RateLimiter(
name="limiter",
endpoint_url="http://localhost:4566",
region="us-east-1",
)
async with limiter.acquire(
entity_id="test-user",
resource="api",
limits=[Limit.per_minute("requests", 100)],
consume={"requests": 1},
) as lease:
print("Rate limited request!")
Declarative Infrastructure¶
For quick iteration, declare infrastructure in code:
from zae_limiter import Repository, RateLimiter
repo = await Repository.open(endpoint_url="http://localhost:4566")
limiter = RateLimiter(repository=repo)
Environment Variables¶
Configure via environment variables for easy switching:
# .env.local
AWS_ENDPOINT_URL=http://localhost:4566
AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test
AWS_DEFAULT_REGION=us-east-1
import os
limiter = RateLimiter(
name="limiter",
endpoint_url=os.getenv("AWS_ENDPOINT_URL"),
region=os.getenv("AWS_DEFAULT_REGION", "us-east-1"),
)
Debugging¶
Check Stack Status¶
# List stacks
aws --endpoint-url=http://localhost:4566 cloudformation list-stacks
# Describe stack
aws --endpoint-url=http://localhost:4566 cloudformation describe-stacks \
--stack-name limiter
Inspect DynamoDB¶
# List tables
aws --endpoint-url=http://localhost:4566 dynamodb list-tables
# Scan table
aws --endpoint-url=http://localhost:4566 dynamodb scan \
--table-name limiter
View Lambda Logs¶
# List functions
aws --endpoint-url=http://localhost:4566 lambda list-functions
# Get logs (replace {name} with your stack name)
aws --endpoint-url=http://localhost:4566 logs tail \
/aws/lambda/{name}-aggregator
LocalStack vs DynamoDB Local¶
| Feature | LocalStack | DynamoDB Local |
|---|---|---|
| DynamoDB | Yes | Yes |
| Streams | Yes | Limited |
| Lambda | Yes | No |
| CloudFormation | Yes | No |
| Cost | Free | Free |
| Fidelity | High | Medium |
Recommendation: Use LocalStack for full integration testing, DynamoDB Local for quick unit tests.
Troubleshooting¶
Connection Refused¶
Solution: Ensure LocalStack is running:
Lambda Not Executing¶
Check Lambda logs:
Ensure the Lambda service is enabled:
docker run -e SERVICES=dynamodb,dynamodbstreams,lambda,cloudformation,logs,iam,cloudwatch,sqs,s3,sts,resourcegroupstaggingapi ...
Slow Performance¶
LocalStack can be slow on first request. Consider:
- Pre-warming containers
- Using persistence for faster restarts
- Reducing DEBUG level
Next Steps¶
- Testing - pytest fixtures and CI configuration
- Development Setup - Local development environment