Override AWS service responses at the operation level, or create fake servers for external API dependencies. Control exactly what your application sees — without changing your code.
Override individual AWS API operations with custom responses. Faked operations bypass the real emulation entirely — your code gets back exactly what you define.
Fake specific operations like GetItem or ReceiveMessage while leaving the rest of the service running normally.
Built-in helpers auto-format responses for each service — DynamoDB JSON, S3 XML, SQS message structures — so you don't have to.
Create a named fake targeting a specific AWS service.
uvx --from local-web-services lws aws-fake create my-s3-fake --service s3Define what specific operations should return. Use service-aware helpers for correctly formatted responses.
# Fake a DynamoDB GetItem with a helper
uvx --from local-web-services lws aws-fake add-operation my-ddb-fake \
--operation get-item \
--item '{"id": "123", "name": "test"}'
# Fake an S3 GetObject with string content
uvx --from local-web-services lws aws-fake add-operation my-s3-fake \
--operation get-object \
--body-string "Hello from S3"
# Fake with a raw response
uvx --from local-web-services lws aws-fake add-operation my-fake \
--operation list-objects-v2 \
--status 200 \
--body-file /path/to/response.xmlWhen your code calls a faked operation, the fake middleware intercepts the request before it reaches the real provider and returns your custom response.
Helpers automatically format responses in the correct service-specific format.
Converts simple JSON to DynamoDB JSON format with type descriptors automatically. --item '{"id": "123", "age": 30}' becomes {"id": {"S": "123"}, "age": {"N": "30"}}.
Returns file content with proper headers (Content-Type, Content-Length, ETag). List operations generate correct S3 XML listings.
Each service has helpers that format responses in the correct structure: SQS XML messages with auto-generated IDs, SSM parameter metadata, Cognito JWT tokens, SNS message IDs, Step Functions execution ARNs, and EventBridge entry responses.
Match requests by headers to return different responses for different inputs.
uvx --from local-web-services lws aws-fake add-operation my-s3-fake \
--operation get-object \
--match-header "x-custom-header=specific-value" \
--status 200 \
--body-string "Custom response for matched header"AWS fakes are stored in .lws/fakes/<name>/ and loaded automatically on startup.
# .lws/fakes/my-s3-fake/config.yaml
name: my-s3-fake
service: s3
enabled: true# .lws/fakes/my-s3-fake/operations/get-object.yaml
operations:
- operation: get-object
match:
headers:
x-custom-header: "specific-value"
response:
status: 200
body: "file content"
content_type: "text/plain"
delay_ms: 100Enable and disable AWS fakes at runtime without restarting ldk dev.
# Enable/disable fakes for a service
uvx --from local-web-services lws aws-fake enable s3
uvx --from local-web-services lws aws-fake disable s3
# Check fake status
uvx --from local-web-services lws aws-fake statusCreate local fake servers for external API dependencies — payment processors, third-party services, partner APIs — so your entire application runs locally without any external calls.
Stop burning through sandbox credits and rate limits during development. Fake servers return realistic responses without making real API calls.
New developers don't need API keys for every third-party service. Fake servers work out of the box with zero configuration.
Define a fake server for each external dependency. Give it a name and optional base configuration.
uvx --from local-web-services lws fake create --name stripe-apiDefine the endpoints your code calls, with the responses you want returned. Use CLI commands or YAML configuration.
uvx --from local-web-services lws fake add-route \
--name stripe-api \
--method POST --path /v1/charges \
--status 200 \
--body '{"id": "ch_{{uuid}}", "status": "succeeded"}'Fake servers start automatically alongside your AWS services when you run ldk dev. Each fake gets its own local endpoint.
Configure your application to use the local fake endpoint instead of the real API. Environment variables are injected automatically for services defined in your IaC.
Fake servers support the protocols your external dependencies use.
Full HTTP method support (GET, POST, PUT, PATCH, DELETE). Match requests by path, headers, query parameters, and body fields. Return custom status codes, headers, and JSON/text bodies.
Match GraphQL queries and mutations by operation name. Return typed response data with support for variables, nested objects, and error responses.
Define service methods and return protobuf-compatible JSON responses. Supports unary calls with status codes and metadata.
Routes define how your fake server responds to incoming requests. Configure them via CLI or YAML.
routes:
- method: POST
path: /v1/charges
status: 200
headers:
Content-Type: application/json
body: |
{
"id": "ch_{{uuid}}",
"amount": {{body.amount}},
"currency": "{{body.currency}}",
"status": "succeeded",
"created": {{timestamp}}
}Routes can match on headers, query parameters, and body fields to return different responses for different inputs.
routes:
# Match by header
- method: GET
path: /v1/customers
match:
headers:
Authorization: "Bearer sk_test_valid"
status: 200
body: '{"data": [{"id": "cus_123"}]}'
# Match by query parameter
- method: GET
path: /v1/customers
match:
query:
email: "not-found@example.com"
status: 200
body: '{"data": []}'
# Match by body field
- method: POST
path: /v1/charges
match:
body:
amount: 99999
status: 402
body: '{"error": {"type": "card_error", "message": "Card declined"}}'Use template variables in response bodies to generate dynamic, realistic responses.
routes:
- method: POST
path: /v1/payments
status: 200
body: |
{
"id": "pay_{{uuid}}",
"amount": {{body.amount}},
"currency": "{{body.currency}}",
"status": "{{random_choice(succeeded,pending,requires_action)}}",
"created": {{timestamp}},
"receipt_number": {{random_int(1000,9999)}}
}Automatically generate fake routes from existing OpenAPI 3.x or Swagger 2.x specifications.
Point lws fake import-spec at an OpenAPI file. Routes are generated for every endpoint with example responses from the spec.
uvx --from local-web-services lws fake import-spec \
--name stripe-api \
--spec openapi.yamlCheck that your fake covers all the endpoints your code actually calls. The validate command compares your fake routes against the spec and reports missing coverage.
uvx --from local-web-services lws fake validate \
--name stripe-api \
--spec openapi.yaml