LocalStack has become a go-to tool for teams that build on AWS but want fast, reliable, and cost-free local environments for development and testing. This guide walks you from zero to production-ready workflows with LocalStack: installing it, wiring it into your application and infrastructure code, using it in CI, and confidently promoting that code to real AWS.
Important: “Production with LocalStack” in this article means production-grade workflows (CI/CD, automated tests, infrastructure validation) that support your production AWS environment. LocalStack itself is not designed to replace AWS for serving production traffic.
Table of Contents
- What is LocalStack (and What It Isn’t)?
- Core Use Cases and Benefits
- Prerequisites and Installation
- First Steps: Running LocalStack
- Configuring AWS CLI and SDKs to Use LocalStack
- Working with Core AWS Services Locally
- Infrastructure as Code with LocalStack
- Designing a Local Development Workflow
- Testing Strategy with LocalStack
- CI/CD Integration: Production-Grade Pipelines
- From LocalStack to Real AWS: Parity and Drift
- Performance, Security, and Cost Considerations
- Troubleshooting and Debugging
- Best Practices Checklist
- Conclusion
- Resources
What is LocalStack (and What It Isn’t)?
LocalStack is a local cloud emulator that mimics many AWS services (S3, DynamoDB, SQS, Lambda, API Gateway, and more) so you can:
- Develop and test AWS-based applications without hitting real AWS.
- Run fast, repeatable integration and system tests in isolation.
- Validate Infrastructure as Code templates (Terraform, CDK, CloudFormation) before deploying.
It runs entirely on your machine (or CI agents), usually via Docker.
What LocalStack is not:
- It is not a drop-in replacement for AWS in production.
- It does not implement every single AWS feature or edge case.
- It should not hold any real secrets or production data.
Think of it as a very realistic simulator and test harness, not the real airplane.
Core Use Cases and Benefits
LocalStack shines in several scenarios:
- Local development: Run your entire “cloud stack” locally, iterate quickly, avoid slow remote deploys.
- Integration testing: Validate your application logic against emulated AWS services.
- Infrastructure testing: Plan/apply Terraform/CDK stacks against LocalStack before deploying to AWS.
- Onboarding: New developers can run everything with a single
docker compose up.
Key benefits:
- Near-zero cloud cost for development & testing.
- Much faster feedback loops compared to deploying to dev AWS accounts.
- Better reproducibility (tests do not depend on shared AWS environments).
- Offline-friendly: work on a plane, train, or low-connectivity environment.
Prerequisites and Installation
Before you start, you should have:
- Docker (recommended way to run LocalStack)
- AWS CLI v2 (optional but highly recommended)
- A recent Python (if using the CLI via
pip) - (Optionally) Node.js, Java, or Python for your application code
Install via Docker
This is the most robust and CI-friendly option.
Pull the latest LocalStack image:
docker pull localstack/localstack
To run it quickly:
docker run --rm -it \
-p 4566:4566 \
-p 4510-4559:4510-4559 \
-e SERVICES="s3,dynamodb,sqs,sns,lambda" \
-e DEBUG=1 \
localstack/localstack
4566is the edge port for almost all services.4510-4559ports are used internally for some services (esp. Pro/Team).
Install via LocalStack CLI (pip)
The CLI is a lightweight wrapper that manages Docker for you.
pip install localstack
Verify:
localstack --version
Then start:
localstack start
# or for detached/background mode
localstack start -d
Note: The CLI will automatically pull and run the Docker image. You still need Docker installed.
Community vs Pro vs Team
- Community (open source):
- Free, GitHub-hosted.
- Supports many core AWS services: S3, SQS, SNS, DynamoDB, Lambda (basic), API Gateway, etc.
- Pro (paid):
- Adds advanced services (e.g., Aurora, Kinesis, CloudWatch Logs with more fidelity, EKS, etc.).
- Extra features like persistence, tracing, and advanced debugging.
- Team/Enterprise:
- Focused on large organizations: multi-user, centralized control, better auth & security, support.
For most “zero to production” workflows, Community is enough. If you need RDS, EKS, or complex data services, Pro may be worth it.
First Steps: Running LocalStack
Quick Start with the CLI
Once installed via pip:
localstack start -d # start in background
localstack status services
You should see output listing services and their status (e.g., running).
To stop:
localstack stop
To reset all state:
localstack stop
localstack start -d
# or
localstack stop --purge # remove volumes/containers
Using Docker Compose for Reproducible Environments
A common pattern is to define LocalStack in docker-compose.yml along with your app and dependencies.
version: "3.8"
services:
localstack:
image: localstack/localstack:latest
container_name: localstack_main
ports:
- "4566:4566"
- "4510-4559:4510-4559"
environment:
- SERVICES=s3,dynamodb,sqs,sns,lambda
- DEBUG=1
- LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY-} # optional for Pro
- AWS_DEFAULT_REGION=us-east-1
volumes:
- "./localstack-data:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
app:
build: .
environment:
- AWS_REGION=us-east-1
- AWS_ACCESS_KEY_ID=test
- AWS_SECRET_ACCESS_KEY=test
- AWS_ENDPOINT_URL=http://localstack:4566
depends_on:
- localstack
ports:
- "8080:8080"
Then:
docker compose up
Your app can reach LocalStack at http://localstack:4566 via the Docker network.
Configuring AWS CLI and SDKs to Use LocalStack
Basic AWS CLI Setup
LocalStack ignores real AWS credentials, but many tools still expect them. Use dummy values:
aws configure
# AWS Access Key ID [None]: test
# AWS Secret Access Key [None]: test
# Default region name [None]: us-east-1
# Default output format [None]: json
To target LocalStack, set the endpoint explicitly:
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_DEFAULT_REGION=us-east-1
aws --endpoint-url=http://localhost:4566 s3 ls
To avoid repeating --endpoint-url, you can use profiles or environment variables with wrappers, but be cautious not to accidentally point production commands to LocalStack or vice versa.
Boto3 (Python) Example
import boto3
import os
LOCALSTACK_ENDPOINT = os.getenv("AWS_ENDPOINT_URL", "http://localhost:4566")
REGION = os.getenv("AWS_REGION", "us-east-1")
session = boto3.Session(
aws_access_key_id="test",
aws_secret_access_key="test",
region_name=REGION,
)
s3 = session.client("s3", endpoint_url=LOCALSTACK_ENDPOINT)
ddb = session.client("dynamodb", endpoint_url=LOCALSTACK_ENDPOINT)
Tip: Always inject the endpoint through configuration (env vars, config files) rather than hard-coding.
Node.js (AWS SDK v3) Example
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
const endpoint = process.env.AWS_ENDPOINT_URL || "http://localhost:4566";
const region = process.env.AWS_REGION || "us-east-1";
const s3 = new S3Client({
region,
endpoint,
forcePathStyle: true, // important for LocalStack S3
credentials: {
accessKeyId: "test",
secretAccessKey: "test",
},
});
async function main() {
const result = await s3.send(new ListBucketsCommand({}));
console.log(result.Buckets);
}
main().catch(console.error);
Note forcePathStyle: true – LocalStack’s S3 emulation typically expects path-style buckets.
Working with Core AWS Services Locally
S3: Buckets and Objects
Create a bucket:
aws --endpoint-url=http://localhost:4566 s3 mb s3://my-bucket
Upload a file:
echo "hello localstack" > hello.txt
aws --endpoint-url=http://localhost:4566 s3 cp hello.txt s3://my-bucket/hello.txt
List objects:
aws --endpoint-url=http://localhost:4566 s3 ls s3://my-bucket
Python example:
s3.put_object(Bucket="my-bucket", Key="hello.txt", Body=b"hello localstack")
resp = s3.get_object(Bucket="my-bucket", Key="hello.txt")
print(resp["Body"].read())
DynamoDB: Tables and Items
Create a table:
aws --endpoint-url=http://localhost:4566 dynamodb create-table \
--table-name Users \
--attribute-definitions AttributeName=UserId,AttributeType=S \
--key-schema AttributeName=UserId,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Put an item:
aws --endpoint-url=http://localhost:4566 dynamodb put-item \
--table-name Users \
--item '{"UserId":{"S":"123"}, "Name":{"S":"Alice"}}'
Scan:
aws --endpoint-url=http://localhost:4566 dynamodb scan --table-name Users
Python example:
ddb.put_item(
TableName="Users",
Item={"UserId": {"S": "123"}, "Name": {"S": "Alice"}},
)
resp = ddb.get_item(
TableName="Users",
Key={"UserId": {"S": "123"}},
)
print(resp["Item"])
SQS & SNS: Messaging Workflows
Create an SQS queue:
QUEUE_URL=$(aws --endpoint-url=http://localhost:4566 sqs create-queue \
--queue-name my-queue \
--query 'QueueUrl' --output text)
echo $QUEUE_URL
Send a message:
aws --endpoint-url=http://localhost:4566 sqs send-message \
--queue-url "$QUEUE_URL" \
--message-body "hello from localstack"
Receive messages:
aws --endpoint-url=http://localhost:4566 sqs receive-message \
--queue-url "$QUEUE_URL"
SNS topic + subscription:
TOPIC_ARN=$(aws --endpoint-url=http://localhost:4566 sns create-topic \
--name my-topic \
--query 'TopicArn' --output text)
aws --endpoint-url=http://localhost:4566 sns subscribe \
--topic-arn "$TOPIC_ARN" \
--protocol sqs \
--notification-endpoint "$QUEUE_URL"
aws --endpoint-url=http://localhost:4566 sns publish \
--topic-arn "$TOPIC_ARN" \
--message "hello via sns"
Now receive-message on the queue should show the SNS-published message.
Infrastructure as Code with LocalStack
Terraform + LocalStack
Add a Terraform provider configuration pointing to LocalStack.
main.tf:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
access_key = "test"
secret_key = "test"
skip_credentials_validation = true
skip_metadata_api_check = true
s3_force_path_style = true
endpoints {
s3 = "http://localhost:4566"
dynamodb = "http://localhost:4566"
sqs = "http://localhost:4566"
sns = "http://localhost:4566"
lambda = "http://localhost:4566"
}
}
resource "aws_s3_bucket" "example" {
bucket = "tf-localstack-bucket"
}
Then:
terraform init
terraform plan
terraform apply
You can verify:
aws --endpoint-url=http://localhost:4566 s3 ls
Tip: Maintain separate provider configurations for LocalStack vs AWS (e.g., via workspaces or separate directories) to avoid accidentally applying LocalStack configs to real AWS.
AWS CDK + LocalStack
Install the CDK and the LocalStack integration plugin.
npm install -g aws-cdk
npm install --save-dev localstack-cdk
In a simple CDK stack (TypeScript):
import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
export class DemoStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new s3.Bucket(this, "DemoBucket", {
bucketName: "cdk-localstack-demo-bucket",
});
}
}
Use localstack-cdk (or the LocalStack CLI) to deploy to LocalStack:
export LOCALSTACK_ENDPOINT=http://localhost:4566
# Option 1: Use CDK and override endpoint via env/config
cdk synth
cdk deploy \
--profile localstack \
--require-approval never
# Option 2 (more modern): Use localstack CLI
localstack aws cdk deploy --app "npx ts-node bin/app.ts"
The localstack aws wrapper automatically injects the LocalStack endpoint.
Serverless Framework / SAM
Serverless Framework (serverless.yml):
service: localstack-demo
provider:
name: aws
runtime: nodejs20.x
stage: local
region: us-east-1
endpoint: http://localhost:4566
iam:
role:
statements:
- Effect: Allow
Action:
- s3:*
Resource: "*"
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
Deploy:
SLS_DEBUG=* serverless deploy --stage local
AWS SAM example:
sam build
sam local start-api \
--env-vars env.json \
--docker-network <your-network> # if you want SAM to reach LocalStack
You can also use LocalStack’s lambda emulator instead of SAM, depending on your workflow.
Designing a Local Development Workflow
Project Structure
One workable layout:
.
├── app/ # application code
│ ├── src/
│ └── tests/
├── infra/
│ ├── terraform/ # or cdk, cloudformation, pulumi, etc.
│ └── localstack/ # local infra configs, seed scripts
├── docker-compose.yml
└── Makefile
Key principles:
- Single command to start the entire environment (
make up,docker compose up). - Configuration uses env vars or config files so you can easily switch between LocalStack and AWS.
- Infra definitions for LocalStack and AWS reuse as much as possible (DRY), making divergences explicit.
Seeding and Resetting State
For reproducible tests, you often need to:
- Create S3 buckets, DynamoDB tables, queues, etc.
- Seed initial data (test users, sample files).
- Reset state between test runs.
Example seed script (seed_localstack.sh):
#!/usr/bin/env bash
set -euo pipefail
ENDPOINT=${AWS_ENDPOINT_URL:-http://localhost:4566}
REGION=${AWS_REGION:-us-east-1}
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_DEFAULT_REGION=$REGION
# S3
aws --endpoint-url="$ENDPOINT" s3 mb s3://my-app-bucket || true
# DynamoDB
aws --endpoint-url="$ENDPOINT" dynamodb create-table \
--table-name Users \
--attribute-definitions AttributeName=UserId,AttributeType=S \
--key-schema AttributeName=UserId,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
>/dev/null 2>&1 || true
# SQS
aws --endpoint-url="$ENDPOINT" sqs create-queue \
--queue-name my-app-queue \
>/dev/null 2>&1 || true
Call this:
./seed_localstack.sh
You can run it:
- Locally when you start the stack.
- As part of your test setup.
- In CI before executing the test suite.
Testing Strategy with LocalStack
Unit vs Integration vs System Tests
Use LocalStack strategically:
- Unit tests: Don’t require LocalStack. Mock AWS SDKs, focus on your logic.
- Integration tests: Use LocalStack to test your AWS interactions end-to-end (Lambda + SQS, S3 events, etc.).
- System / E2E tests: Run your whole app + LocalStack + database + other services.
Rule of thumb: Only test with LocalStack what you cannot confidently test with pure mocks.
Python Example: pytest + LocalStack
Use pytest fixtures and the LocalStack CLI/Docker.
conftest.py:
import os
import subprocess
import time
import boto3
import pytest
LOCALSTACK_ENDPOINT = "http://localhost:4566"
REGION = "us-east-1"
@pytest.fixture(scope="session", autouse=True)
def localstack_env():
# Start LocalStack via Docker compose or CLI before tests
# Here we assume it's already running; otherwise, you can manage the lifecycle here.
os.environ["AWS_ACCESS_KEY_ID"] = "test"
os.environ["AWS_SECRET_ACCESS_KEY"] = "test"
os.environ["AWS_DEFAULT_REGION"] = REGION
os.environ["AWS_ENDPOINT_URL"] = LOCALSTACK_ENDPOINT
yield
# Optionally teardown/reset state
@pytest.fixture(scope="session")
def s3_client():
return boto3.client("s3", endpoint_url=LOCALSTACK_ENDPOINT, region_name=REGION)
@pytest.fixture(scope="session", autouse=True)
def setup_localstack_resources(s3_client):
bucket_name = "test-bucket"
try:
s3_client.create_bucket(Bucket=bucket_name)
except s3_client.exceptions.BucketAlreadyOwnedByYou:
pass
yield
test_s3_integration.py:
def test_upload_and_read(s3_client):
bucket = "test-bucket"
key = "hello.txt"
body = b"hello from pytest"
s3_client.put_object(Bucket=bucket, Key=key, Body=body)
resp = s3_client.get_object(Bucket=bucket, Key=key)
assert resp["Body"].read() == body
Run:
pytest -m "integration"
You can tag tests requiring LocalStack with a marker and run them conditionally in CI.
Testcontainers + LocalStack
For JVM, Node, or Python projects, Testcontainers can manage LocalStack containers automatically in tests.
Java (JUnit 5) example:
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import software.amazon.awssdk.services.s3.S3Client;
import static org.testcontainers.containers.localstack.LocalStackContainer.Service.S3;
@Testcontainers
public class LocalstackIT {
@Container
private static final LocalStackContainer LOCALSTACK =
new LocalStackContainer("localstack/localstack:latest")
.withServices(S3);
@Test
void testS3() {
S3Client s3 = S3Client.builder()
.endpointOverride(LOCALSTACK.getEndpointOverride(S3))
.credentialsProvider(LOCALSTACK.getDefaultCredentialsProvider())
.region(LOCALSTACK.getRegion())
.build();
s3.createBucket(b -> b.bucket("test-bucket"));
// ...
}
}
This pattern scales well for complex integration testing in CI, as Testcontainers handles container lifecycle.
CI/CD Integration: Production-Grade Pipelines
To make LocalStack a first-class citizen in your delivery pipeline:
- Start LocalStack in CI (Docker service, container, or Testcontainers).
- Deploy or seed your infrastructure to LocalStack (Terraform/CDK/CloudFormation).
- Run your integration/system tests against it.
- Only if they pass, deploy to real AWS.
GitHub Actions Example
.github/workflows/ci.yml:
name: CI
on:
push:
branches: [ main ]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
services:
localstack:
image: localstack/localstack:latest
ports:
- 4566:4566
env:
SERVICES: s3,dynamodb,sqs,sns,lambda
AWS_DEFAULT_REGION: us-east-1
options: >-
--health-cmd="curl -f http://localhost:4566/health || exit 1"
--health-interval=5s
--health-timeout=2s
--health-retries=20
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
pip install -r requirements.txt
- name: Wait for LocalStack
run: |
for i in $(seq 1 30); do
if curl -s http://localhost:4566/health | grep "\"initScripts\": \"initialized\""; then
echo "LocalStack is ready"
break
fi
echo "Waiting for LocalStack..."
sleep 2
done
- name: Seed LocalStack
env:
AWS_ENDPOINT_URL: http://localhost:4566
run: |
./infra/localstack/seed_localstack.sh
- name: Run tests
env:
AWS_ENDPOINT_URL: http://localhost:4566
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
run: |
pytest -m "integration or e2e"
GitLab CI Example
.gitlab-ci.yml:
stages:
- test
integration_tests:
stage: test
image: python:3.11
services:
- name: localstack/localstack:latest
alias: localstack
variables:
AWS_ENDPOINT_URL: "http://localstack:4566"
AWS_ACCESS_KEY_ID: "test"
AWS_SECRET_ACCESS_KEY: "test"
AWS_DEFAULT_REGION: "us-east-1"
script:
- pip install -r requirements.txt
- ./infra/localstack/seed_localstack.sh
- pytest -m "integration"
This pattern provides consistency between local and CI environments: same emulator, same infra scripts, same tests.
From LocalStack to Real AWS: Parity and Drift
Configuration Parity
To keep LocalStack and AWS environments aligned:
- Use the same IaC (Terraform/CDK/CloudFormation) where possible.
- Keep regions consistent (e.g.,
us-east-1everywhere by default). - Parameterize environment-specific values:
- Bucket names:
my-app-${env} - Table names:
users-${env} - Queue names:
my-queue-${env}
- Bucket names:
Example with Terraform variables:
variable "env" {
type = string
default = "local"
}
resource "aws_s3_bucket" "app" {
bucket = "my-app-${var.env}"
}
- For LocalStack:
env = "local" - For dev/stage/prod AWS:
env = "dev",env = "prod"etc.
Feature Gaps and Workarounds
Some AWS features are partially or not implemented in LocalStack (especially in Community edition):
- IAM policies and complex auth flows
- Certain managed services (Aurora, EMR, EKS, etc.)
- Some event triggers and service integrations
Workarounds:
- Abstract cloud interactions behind interfaces; for LocalStack, use simpler patterns that are supported.
- Use contract tests: validate that the subset of AWS you rely on behaves the same in real AWS as it does in LocalStack.
- For unsupported services, consider:
- Using mocks for those parts.
- Using a shared dev AWS account for a smaller set of tests.
Always maintain a minimal test suite against real AWS before production deploys, especially if you rely on advanced or newly released services.
Performance, Security, and Cost Considerations
Performance
- LocalStack is fast, but heavy stacks (many services, Lambdas, large datasets) still consume CPU/memory.
- Optimize:
- Only enable services you need via
SERVICESenv var. - Use ephemeral stacks per test run and tear down afterwards.
- For integration tests, prefer smaller, focused scenarios over full end-to-end flows.
- Only enable services you need via
Security
- Do not store real secrets (API keys, DB passwords) in LocalStack.
- Keep your LocalStack ports bound to localhost when running on laptops.
- In CI, ensure LocalStack is on an isolated network and not reachable from the public internet.
Cost
- LocalStack itself is free in Community edition.
- Pro/Team licenses add cost but are often cheaper than large multi-account AWS dev setups.
- Biggest savings come from:
- Fewer dev/test AWS environments.
- Less time and money spent on provisioning and cleaning up AWS resources for tests.
Troubleshooting and Debugging
Common issues and remedies:
“Connection refused” / Cannot reach LocalStack
- Ensure container is running:
docker ps. - Check port mappings:
4566should be open. - If using Docker Compose networks, ensure you use
http://localstack:4566inside containers,http://localhost:4566on host.
- Ensure container is running:
Services not available / 404 errors
Verify
SERVICESenv var includes the required service.Check
/healthendpoint:curl http://localhost:4566/health
S3 path vs virtual-host style issues
- Use path-style configuration:
- AWS SDKs:
forcePathStyle: true(JS) /path_style = trueequivalent. - Terraform:
s3_force_path_style = true.
- AWS SDKs:
- Use path-style configuration:
IAM / permissions-related errors
- LocalStack often relaxes IAM checks, but some flows still require minimal configuration.
- For testing, start simple: allow
*actions on*resources, then tighten if needed.
Lambda runtime errors
- Inspect LocalStack logs (
docker logs localstack_main). - Ensure:
- Handler name matches.
- Runtime is supported.
- Code is packaged correctly (zip or image).
- Use
DEBUG=1for verbose logs.
- Inspect LocalStack logs (
When in doubt, check the LocalStack logs. They are often more informative than client error messages.
Best Practices Checklist
Use this as a quick reference when building a LocalStack-based workflow:
- Run LocalStack via Docker (direct or via CLI) for consistency.
- Configure AWS SDKs and CLI to use endpoint URLs from env/config, not hard-coded.
- Keep infrastructure definitions shared between LocalStack and AWS, parameterized by environment.
- Use LocalStack only for integration/system tests; keep pure unit tests free of it.
- Seed and reset LocalStack state via scripts or IaC, not manual steps.
- Wire LocalStack into CI pipelines for repeatable integration tests.
- Maintain a small smoke-test suite against real AWS to catch emulator gaps.
- Avoid storing real secrets in LocalStack environments.
- Log and monitor LocalStack in CI to debug failing tests.
- Periodically update LocalStack image and revalidate behavior to catch breaking changes early.
Conclusion
LocalStack is a powerful way to bring your AWS-based architecture close to your keyboard:
- Developers gain fast, isolated environments without cloud friction.
- Test suites become more robust, reproducible, and cheaper to run.
- Infrastructure as Code pipelines become safer, as you validate changes locally before they ever touch AWS.
The key to “zero to production” success is treating LocalStack as part of your production tooling:
- Integrate it into IaC workflows.
- Embed it into CI/CD.
- Use it selectively where it adds the most value (integration & system tests).
Used thoughtfully, LocalStack can dramatically improve the reliability, speed, and confidence of teams building on AWS.
Resources
Official and core documentation:
LocalStack Docs:
https://docs.localstack.cloud/LocalStack GitHub (Community Edition):
https://github.com/localstack/localstackLocalStack AWS CLI Wrapper (
localstack aws):
https://docs.localstack.cloud/user-guide/integrations/aws-cli/LocalStack Terraform Integration:
https://docs.localstack.cloud/user-guide/integrations/terraform/LocalStack CDK Integration:
https://docs.localstack.cloud