ForEach and ToJsonString

Fn::ForEach, Fn::Length and Fn::ToJsonString

A loop's fragment can hold several resources that refer to each other. In infra/stages.yaml, each name in the Stages list (default dev,test) gets an orders table and a parameter holding its ARN, via a computed Fn::GetAtt:

infra/stages.yaml (Resources): an orders table and its ARN parameter per stageYAML
  Fn::ForEach::StageOrders:
    - Stage
    - !Ref Stages
    - ${Stage}Orders:
        Type: AWS::DynamoDB::Table
        Properties:
          TableName: !Sub booknest-${Stage}-orders
          BillingMode: PAY_PER_REQUEST
          AttributeDefinitions: [{AttributeName: orderId, AttributeType: S}]
          KeySchema: [{AttributeName: orderId, KeyType: HASH}]
      ${Stage}OrdersArn:
        Type: AWS::SSM::Parameter
        Properties:
          Name: !Sub /booknest/${Stage}/orders-arn
          Type: String
          Value: {Fn::GetAtt: [!Sub "${Stage}Orders", Arn]}

The rest of the file adds a condition, SeveralStages: {Fn::Not: [{Fn::Equals: [{Fn::Length: !Ref Stages}, 1]}]}, guarding a StageSummary parameter set to {Fn::ToJsonString: {count: {Fn::Length: !Ref Stages}, names: !Ref Stages}}.

Deploying the loop and reading the parameters it producedShell
aws cloudformation deploy --stack-name booknest-stages --template-file stages.yaml \
  --capabilities CAPABILITY_AUTO_EXPAND
aws ssm get-parameters-by-path --path /booknest --recursive --output text \
  --query 'Parameters[].[Name,Value]'
Output
...
Successfully created/updated stack - booknest-stages
/booknest/stages   {"count":{"Fn::Length":{"Ref":"Stages"}},"names":{"Ref":"Stages"}}
/booknest/dev/orders-arn   arn:aws:dynamodb:us-east-1:000000000000:table/booknest-dev-orders
/booknest/test/orders-arn   arn:aws:dynamodb:us-east-1:000000000000:table/booknest-test-orders

Each Fn::GetAtt resolved, and Fn::Length returned 2, keeping StageSummary (a Stages=solo deploy omits it). Fn::ToJsonString repeats LocalStack 63,725 's gap from Fn::ForEach; AWS 24 stores {"count":2,"names":["dev","test"]}. Keep loops small and flat: every iteration counts toward the 500-resource quota.