E-commerce Microservices (CDK)¶
Source: examples/ecommerce-microservices.yaml
To check and price this model from a clone of the repository:
infra-cost-model validate examples/ecommerce-microservices.yaml
infra-cost-model compute --time-basis monthly examples/ecommerce-microservices.yaml
# Example: E-commerce Microservices (CDK)
# Demonstrates: shared-node accumulation, external percentage pricing (Stripe),
# conditional branching, multi-hop depth, SQS decoupling.
#
# Issue: https://github.com/elecnix/infra-cost-model/issues/8
version: "1.0"
workflow:
name: ecommerce-api
entry: aws_apigatewayv2_api.ecommerce_api
# A mid-size store: 10 API requests a minute, 40% of which create an order.
# That is about 175,000 orders a month, or $8.8M of sales at $50 each.
frequency:
unit: perMinute
value: 10
nodes:
aws_apigatewayv2_api.ecommerce_api:
nodeType: routing
resourceAddress: aws_apigatewayv2_api.ecommerce_api
provider: aws
region: us-east-1
service: AmazonAPIGatewayHTTP
usageMetrics:
requests: { unit: requests, value: 1 }
# An HTTP API has no egress price of its own. AWS bills the response bytes
# as data transfer out to the internet.
data_transfer.ecommerce_api_egress:
nodeType: external
resourceAddress: data_transfer.ecommerce_api_egress
provider: aws
region: us-east-1
service: AWSDataTransfer
usageMetrics:
internetOutGb: { unit: GB, value: 0.00002 } # 20KB per request
aws_lambda_function.auth:
nodeType: compute
resourceAddress: aws_lambda_function.auth
provider: aws
region: us-east-1
service: AWSLambda
usageMetrics:
invocations: { unit: requests, value: 1 }
avgDurationMs: { unit: ms, value: 20 }
memoryMb: { unit: MB, value: 128 }
aws_lambda_function.get_products:
nodeType: compute
resourceAddress: aws_lambda_function.get_products
provider: aws
region: us-east-1
service: AWSLambda
usageMetrics:
invocations: { unit: requests, value: 1 }
avgDurationMs: { unit: ms, value: 100 }
memoryMb: { unit: MB, value: 256 }
aws_lambda_function.create_order:
nodeType: compute
resourceAddress: aws_lambda_function.create_order
provider: aws
region: us-east-1
service: AWSLambda
usageMetrics:
invocations: { unit: requests, value: 1 }
avgDurationMs: { unit: ms, value: 200 }
memoryMb: { unit: MB, value: 512 }
aws_lambda_function.process_payment:
nodeType: compute
resourceAddress: aws_lambda_function.process_payment
provider: aws
region: us-east-1
service: AWSLambda
usageMetrics:
invocations: { unit: requests, value: 1 }
avgDurationMs: { unit: ms, value: 500 }
memoryMb: { unit: MB, value: 256 }
aws_lambda_function.fulfill_order:
nodeType: compute
resourceAddress: aws_lambda_function.fulfill_order
provider: aws
region: us-east-1
service: AWSLambda
usageMetrics:
invocations: { unit: requests, value: 1 }
avgDurationMs: { unit: ms, value: 300 }
memoryMb: { unit: MB, value: 256 }
aws_dynamodb_table.products:
nodeType: storage
resourceAddress: aws_dynamodb_table.products
provider: aws
region: us-east-1
service: AmazonDynamoDB
usageMetrics:
# One read per call. The edge from get_products carries rate 3.
readRequests: { unit: requests, value: 1 }
aws_dynamodb_table.orders:
nodeType: storage
resourceAddress: aws_dynamodb_table.orders
provider: aws
region: us-east-1
service: AmazonDynamoDB
usageMetrics:
writeRequests: { unit: requests, value: 1 }
aws_sqs_queue.order_queue:
nodeType: routing
resourceAddress: aws_sqs_queue.order_queue
provider: aws
region: us-east-1
service: AmazonSQS
usageMetrics:
messagesSent: { unit: requests, value: 1 }
external_api.stripe:
nodeType: external
resourceAddress: external_api.stripe
provider: external
service: Stripe
region: global
pricingModel: percentage
# The escape hatch (Principles 9 and 13). The catalog has no Stripe rows
# and percentage pricing reads its rates from the model, so this node
# states them. The AWS nodes in every example price from the catalog.
pricingRates:
percentageRate: 0.029 # 2.9% per transaction
fixedPerTransaction: 0.30 # $0.30 per transaction
usageMetrics:
transactionVolume: { unit: USD, value: 50 } # $50 per order (average order value)
aws_sns_topic.notifications:
nodeType: routing
resourceAddress: aws_sns_topic.notifications
provider: aws
region: us-east-1
service: AmazonSNS
usageMetrics:
publishes: { unit: requests, value: 1 }
edges:
# Every response leaves AWS as data transfer out
- from: aws_apigatewayv2_api.ecommerce_api
to: data_transfer.ecommerce_api_egress
rate: 1
# Entry → Auth (every request authenticated)
- from: aws_apigatewayv2_api.ecommerce_api
to: aws_lambda_function.auth
rate: 1
# Auth branching: 60% browse, 40% create order
- from: aws_lambda_function.auth
to: aws_lambda_function.get_products
rate: 0.6
- from: aws_lambda_function.auth
to: aws_lambda_function.create_order
rate: 0.4
# Browse path: get_products → DynamoDB products (3 reads per call)
- from: aws_lambda_function.get_products
to: aws_dynamodb_table.products
rate: 3
type: read
# Create order path: write to DynamoDB, enqueue to SQS
- from: aws_lambda_function.create_order
to: aws_dynamodb_table.orders
rate: 1
type: write
- from: aws_lambda_function.create_order
to: aws_sqs_queue.order_queue
rate: 1
# Async path: SQS → process_payment
- from: aws_sqs_queue.order_queue
to: aws_lambda_function.process_payment
rate: 1
# Payment processing: external Stripe + conditional fulfillment (95%)
- from: aws_lambda_function.process_payment
to: external_api.stripe
rate: 1
- from: aws_lambda_function.process_payment
to: aws_lambda_function.fulfill_order
rate: 0.95 # 5% payment failures
# Fulfillment: update DynamoDB + send notification
- from: aws_lambda_function.fulfill_order
to: aws_dynamodb_table.orders
rate: 1
type: write
- from: aws_lambda_function.fulfill_order
to: aws_sns_topic.notifications
rate: 1