Guide · AWS CloudFormation · StackSets · Multi-Account

CloudFormation StackSets for Multi-Account MCP Server Deployments

CloudFormation StackSets deploy a single CloudFormation template to multiple AWS accounts and regions simultaneously, maintaining stack instances in each target. For MCP server infrastructure, StackSets are the right tool when you need to deploy the same MCP server setup — IAM roles, security groups, VPC endpoints, or Lambda functions — across a fleet of customer accounts, multiple regional deployments, or all accounts within an AWS Organization. Three StackSets concepts matter most: SELF_MANAGED vs SERVICE_MANAGED — the permission model; SERVICE_MANAGED integrates with AWS Organizations and is the modern default; auto-deployment — automatically deploy to new accounts added to a target Organizational Unit; operation preferences — control how many accounts are updated concurrently and what failure percentage halts the rollout. StackSets do not support drift detection per-account by default; per-stack-instance drift must be triggered separately.

TL;DR

Use SERVICE_MANAGED permission model with AWS Organizations. Designate a DELEGATED_ADMIN member account for StackSets management (not the management account). Target OUs not individual account IDs. Set AutoDeployment.Enabled: true for new account onboarding. Use MaxConcurrentPercentage: 25 and FailureTolerancePercentage: 10 for safe production rollouts.

SELF_MANAGED vs SERVICE_MANAGED

The permission model determines how CloudFormation assumes roles in target accounts:

# SELF_MANAGED — manual role setup in every target account
# Requires: AWSCloudFormationStackSetAdministrationRole in administrator account
#           AWSCloudFormationStackSetExecutionRole in every target account
# Use when: Organizations is not enabled, or cross-org deployments needed
# Admin must manually create IAM roles in target accounts before first deployment

# SERVICE_MANAGED — integrates with AWS Organizations
# CloudFormation assumes service-linked roles automatically — no manual role creation
# Requires: Organizations with all features enabled
# Use when: deploying within your own AWS Organization (recommended)

# Creating a SERVICE_MANAGED StackSet
aws cloudformation create-stack-set \
  --stack-set-name mcp-server-baseline \
  --template-body file://mcp-baseline.yaml \
  --permission-model SERVICE_MANAGED \
  --auto-deployment \
    Enabled=true,RetainStacksOnAccountRemoval=false \
  --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM

# For SELF_MANAGED — no --auto-deployment, specify administrator role
aws cloudformation create-stack-set \
  --stack-set-name mcp-server-baseline \
  --template-body file://mcp-baseline.yaml \
  --permission-model SELF_MANAGED \
  --administration-role-arn arn:aws:iam::111111111111:role/AWSCloudFormationStackSetAdministrationRole \
  --execution-role-name AWSCloudFormationStackSetExecutionRole

With SERVICE_MANAGED and AutoDeployment.Enabled: true, new accounts added to the target OU automatically receive stack instances deployed. RetainStacksOnAccountRemoval: false means the stack is deleted when an account moves out of the OU — set true if you want stack instances to persist after account removal (useful for audit logging resources that must be retained).

DELEGATED_ADMIN — managing StackSets from a member account

By default, only the AWS Organizations management account can create SERVICE_MANAGED StackSets. The DELEGATED_ADMIN feature lets you designate a member account (e.g., a dedicated platform account) to manage StackSets without using the management account for day-to-day operations:

# Register a member account as DELEGATED_ADMIN for CloudFormation StackSets
# Run this from the management account
aws organizations register-delegated-administrator \
  --account-id 222222222222 \
  --service-principal stacksets.cloudformation.amazonaws.com

# Verify delegation
aws organizations list-delegated-administrators \
  --service-principal stacksets.cloudformation.amazonaws.com

# From the delegated admin account (222222222222) — create StackSets targeting OUs
aws cloudformation create-stack-instances \
  --stack-set-name mcp-server-baseline \
  --deployment-targets \
    OrganizationalUnitIds="ou-root-abc12345" \
  --regions us-east-1 eu-west-1 ap-southeast-1 \
  --call-as DELEGATED_ADMIN    # required when operating from delegated admin account
  --operation-preferences \
    MaxConcurrentPercentage=25,FailureTolerancePercentage=10,RegionConcurrencyType=PARALLEL

# Deregister when no longer needed
aws organizations deregister-delegated-administrator \
  --account-id 222222222222 \
  --service-principal stacksets.cloudformation.amazonaws.com

All StackSets API calls from the delegated admin account require --call-as DELEGATED_ADMIN. Without this flag, the call is treated as a SELF_MANAGED operation and fails if the account doesn't have the legacy admin role. The management account can always manage StackSets without this flag.

Deployment targets — OU vs account IDs

Target OUs for scalability — targeting individual account IDs requires updating the StackSet every time an account is added. OU targeting with auto-deployment handles new accounts automatically:

# List OUs in the organization (run from management or delegated admin account)
aws organizations list-organizational-units-for-parent \
  --parent-id r-xxxx   # root ID from describe-organization

# Create stack instances targeting an OU (all accounts in the OU)
aws cloudformation create-stack-instances \
  --stack-set-name mcp-server-baseline \
  --deployment-targets \
    OrganizationalUnitIds="ou-prod-abc12345" \
  --regions us-east-1 eu-west-1 \
  --call-as DELEGATED_ADMIN

# Per-account parameter overrides — customize per account or region
aws cloudformation create-stack-instances \
  --stack-set-name mcp-server-baseline \
  --deployment-targets \
    Accounts="123456789012,234567890123" \
  --regions us-east-1 \
  --parameter-overrides \
    ParameterKey=Environment,ParameterValue=prod \
    ParameterKey=AlertEmail,UsePreviousValue=true \
  --call-as DELEGATED_ADMIN

# Check stack instance status per account
aws cloudformation list-stack-instances \
  --stack-set-name mcp-server-baseline \
  --call-as DELEGATED_ADMIN \
  --query "Summaries[*].{Account:Account,Region:Region,Status:Status,Reason:StatusReason}" \
  --output table

Stack instance statuses: CURRENT — the instance is up to date with the StackSet template and parameters; OUTDATED — the StackSet has been updated but the instance hasn't been updated yet; INOPERABLE — the stack instance failed and is in an unrecoverable state (requires manual intervention). OUTDATED instances do not auto-update — you must run update-stack-instances to apply pending changes.

Operation preferences — concurrent rollout control

Operation preferences control how fast StackSets propagates changes and what failure rate triggers a halt. Setting these correctly is the difference between a safe rolling deployment and a fleet-wide outage:

# Update all stack instances — with safe rollout settings
aws cloudformation update-stack-set \
  --stack-set-name mcp-server-baseline \
  --template-body file://mcp-baseline-v2.yaml \
  --capabilities CAPABILITY_IAM \
  --call-as DELEGATED_ADMIN \
  --operation-preferences '{
    "RegionConcurrencyType": "PARALLEL",
    "MaxConcurrentPercentage": 25,
    "FailureTolerancePercentage": 10,
    "RegionOrder": ["us-east-1", "eu-west-1", "ap-southeast-1"]
  }'

# Operation preference fields explained:
# MaxConcurrentCount: absolute number of accounts to update simultaneously
# MaxConcurrentPercentage: percentage of target accounts to update simultaneously
#   → 25% means 1 in 4 accounts updates at a time — slows rollout but limits blast radius
# FailureToleranceCount: number of account failures before operation is halted
# FailureTolerancePercentage: percentage of failures before halt
#   → 10% means if 10% of accounts fail, the entire operation stops
# RegionConcurrencyType: SEQUENTIAL (one region at a time) or PARALLEL (all regions at once)
# RegionOrder: order to deploy regions in when RegionConcurrencyType is SEQUENTIAL
#   → deploy to primary region first for disaster recovery sequencing

# For production changes — conservative settings
# MaxConcurrentPercentage: 10, FailureTolerancePercentage: 5

# For non-critical baseline infrastructure — faster settings
# MaxConcurrentPercentage: 50, FailureTolerancePercentage: 20

MCP server baseline template — common StackSet use case

A baseline template for deploying MCP server monitoring infrastructure across all accounts in an organization — IAM role, CloudWatch log group, and SSM parameter for the AliveMCP monitoring endpoint:

AWSTemplateFormatVersion: "2010-09-09"
Description: "MCP Server Monitoring Baseline — deployed via StackSets to all accounts"

Parameters:
  Environment:
    Type: String
    AllowedValues: [production, staging, development]
    Default: production
  MonitoringEndpoint:
    Type: String
    Description: AliveMCP monitoring collector endpoint
    Default: "https://ingest.alivemcp.com/v1/probe"

Resources:
  # IAM role for MCP server — allows AliveMCP to call health check
  McpMonitoringRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "McpMonitoring-${Environment}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: "arn:aws:iam::999999999999:root"  # AliveMCP account
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                sts:ExternalId: !Sub "${AWS::AccountId}-mcp-monitoring"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess

  # CloudWatch log group for MCP server tool calls
  McpToolCallLogs:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub "/mcp/tool-calls/${Environment}"
      RetentionInDays: 30

  # SSM Parameter — store monitoring config accessible to Lambda
  McpMonitoringEndpoint:
    Type: AWS::SSM::Parameter
    Properties:
      Name: !Sub "/mcp/${Environment}/monitoring-endpoint"
      Type: String
      Value: !Ref MonitoringEndpoint
      Description: AliveMCP ingest endpoint for this account

Outputs:
  MonitoringRoleArn:
    Value: !GetAtt McpMonitoringRole.Arn
    Export:
      Name: !Sub "${AWS::StackName}-MonitoringRoleArn"

Monitor MCP servers across all your accounts

StackSets deploy infrastructure to multiple accounts, but monitoring each MCP endpoint individually is a separate problem. AliveMCP aggregates health data across all your MCP server deployments and pages the right team when any endpoint goes down — regardless of which account it's in.

Join the waitlist →