Skip to content

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