CloudFormation
Protocol: Query (XML) — POST http://localhost:4566/ with Action= parameter
Endpoint: POST http://localhost:4566/
Supported Actions
| Action | Description |
|---|---|
DescribeStacks |
Get stack status and outputs |
CreateStack |
Deploy a CloudFormation template |
UpdateStack |
Update an existing stack |
DeleteStack |
Delete a stack and its resources |
UpdateTerminationProtection |
- |
CreateChangeSet |
Create a change set |
DescribeChangeSet |
Get change set details (no computed diff/preview) |
ExecuteChangeSet |
Apply a change set |
DeleteChangeSet |
Delete a change set |
ListChangeSets |
List change sets for a stack |
DescribeStackEvents |
Get stack creation/update event history |
DescribeStackResources |
Get all resources in a stack |
ListStackResources |
List resource summaries |
GetTemplate |
Retrieve the template body |
GetTemplateSummary |
Summarize a template's Parameters, Resources and Transform sections, by StackName, TemplateBody or TemplateURL |
ValidateTemplate |
Accepted; returns success without validating (stub) |
ListStacks |
List stacks by status |
ListExports |
- |
SetStackPolicy |
Accepted; no-op (stub — stack policies are not enforced) |
GetStackPolicy |
Accepted; returns an empty policy (stub) |
DescribeStackResource |
Get a specific stack resource |
CreateStackSet |
Create a stack set from a template |
DescribeStackSet |
Get stack set details |
ListStackSets |
List stack sets |
UpdateStackSet |
Update the stack set and re-apply to existing instances |
DeleteStackSet |
Delete an empty stack set |
CreateStackInstances |
Provision instances into target accounts/regions |
ListStackInstances |
List instances (optionally filtered by account/region) |
DescribeStackInstance |
- |
DeleteStackInstances |
Remove instances and their resources |
ListStackSetOperations |
List operations performed on a stack set |
DescribeStackSetOperation |
- |
Supported Resource Types
Resource types provisioned during CreateStack / UpdateStack / DeleteStack. Each delegates to
the backing service and sets a real physical ID plus the Ref / Fn::GetAtt attributes used by
cross-resource references.
Adding a type? See Adding a CloudFormation Resource Type. Types live in per-service provisioners under
services/cloudformation/provisioners/; keep this table in step with them.
| Service | Resource types |
|---|---|
| S3 | Bucket, BucketPolicy (accepted; policy not enforced) |
| SQS | Queue, QueuePolicy (accepted; policy not enforced) |
| SNS | Topic, Subscription |
| DynamoDB | Table, GlobalTable |
| Lambda | Function (Zip via S3/inline ZipFile, and Image), LayerVersion, EventSourceMapping (SQS, Kinesis, DynamoDB Streams), Version, Alias (also what SAM's AutoPublishAlias expands into) |
| IAM | Role, User, AccessKey, Policy, ManagedPolicy, InstanceProfile |
| SSM | Parameter |
| KMS | Key, Alias |
| Secrets Manager | Secret, SecretTargetAttachment |
| ECR | Repository |
| ECS | Cluster, TaskDefinition, Service |
| EKS | Cluster, Nodegroup |
| RDS | DBInstance, DBCluster, DBSubnetGroup, DBParameterGroup, DBClusterParameterGroup (DBInstance/DBCluster start real containers) |
| EC2 | VPC, Subnet, SecurityGroup (including inline SecurityGroupIngress/SecurityGroupEgress), SecurityGroupIngress, SecurityGroupEgress, InternetGateway, RouteTable, SubnetRouteTableAssociation, Route, NatGateway, EIP, Instance, LaunchTemplate, VPCGatewayAttachment, NetworkAcl, NetworkAclEntry, SubnetNetworkAclAssociation, FlowLog |
| Elastic Load Balancing v2 | LoadBalancer, TargetGroup, Listener, ListenerRule |
| Auto Scaling | LaunchConfiguration, AutoScalingGroup, LifecycleHook |
| Route 53 | HostedZone, RecordSet |
| API Gateway (v1) | RestApi, Resource, Authorizer, Method, Deployment, Stage, Account |
| API Gateway v2 | Api, Route, Integration, Stage, Deployment |
| Step Functions | StateMachine |
| Batch | ComputeEnvironment, JobQueue, JobDefinition |
| Cognito | UserPool, UserPoolClient |
| EventBridge | Rule, EventBus, EventBusPolicy |
| Pipes | Pipe |
| Kinesis | Stream |
| Kinesis Data Firehose | DeliveryStream |
| CloudWatch | Alarm |
| CloudWatch Logs | LogGroup |
| CloudFormation | Stack (nested stacks), CustomResource and Custom::* (Lambda-backed) |
| CDK | CDK::Metadata (accepted; no-op) |
All other resource types are accepted without error and assigned a synthetic physical ID (with an
arn:aws:stub:::<logicalId> ARN attribute), so templates with unsupported types still reach
CREATE_COMPLETE rather than failing.
EventBridge Event Buses
AWS::Events::EventBus creates a real custom EventBridge bus. Name is required, Ref returns
the bus name, and Fn::GetAtt supports Arn and Name. Description and Tags are applied when
the bus is created. Rules that reference the bus are removed before stack deletion.
The current implementation is limited to custom buses with the Name, Description, Tags, and
Policy properties. EventSourceName, KmsKeyIdentifier, DeadLetterConfig, and LogConfig are
rejected with ValidationError instead of being silently ignored. AWS models a Name change as
resource replacement; Floci currently rejects that update until generic replacement handling is
available. Policy is applied when the bus is created. Changing Description, Tags, or Policy
during UpdateStack is rejected until transactional resource rollback is available; this prevents a
failed stack update from leaving the live bus in the rejected configuration.
Secrets Manager Target Attachments
AWS::SecretsManager::SecretTargetAttachment adds the target's database connection fields to the
referenced secret while preserving credentials and custom fields. Ref and Fn::GetAtt Id return
the complete secret ARN, only one attachment can own a secret, and deleting the attachment removes
only its managed connection fields.
Supported target types are:
AWS::RDS::DBInstanceAWS::RDS::DBClusterAWS::DocDB::DBInstanceAWS::DocDB::DBCluster
Redshift clusters, Redshift Serverless namespaces, and DocumentDB Elastic clusters are not supported
because their backing services are not implemented. A SecretId change is applied in place rather
than reproducing CloudFormation's replacement event sequence; failed changes restore affected secret
data and attachment ownership.
Auto Scaling Launch Template Resolution
AWS::AutoScaling::AutoScalingGroup resolves its launch template through any of the shapes AWS
accepts, not only by name:
LaunchTemplatewithLaunchTemplateIdorLaunchTemplateName(plus an optionalVersion). The id and name are distinct lookup keys, so anlt-id is matched as an id rather than being treated as a name.- A
Refto an in-stackAWS::EC2::LaunchTemplate, whoseRefreturns thelt-id and whoseFn::GetAtt LatestVersionNumbersupplies the version. MixedInstancesPolicy→LaunchTemplate→LaunchTemplateSpecification, includingOverrides[].InstanceTypeandInstancesDistribution(OnDemandBaseCapacity,OnDemandPercentageAboveBaseCapacity,SpotAllocationStrategy). A non-integer where AWS expects a number fails the stack rather than being dropped.
Lambda Stack Updates
AWS::Lambda::Function resources are reconciled during UpdateStack in the same shape as CloudFormation/CDK deployments:
- A no-op redeploy keeps the existing physical function name and does not call Lambda update APIs, so warm containers can be reused.
- Code and mutable configuration changes update the existing function in place.
- Replacement-only changes such as
FunctionNameorPackageTypechanges create a replacement function and remove the old one. - S3-backed code stays linked through
S3Bucket/S3Key, so Lambda's reactive S3 sync continues to work for functions created by CloudFormation or CDK.
RDS Credential Dynamic References
AWS::RDS::DBInstance and AWS::RDS::DBCluster resolve CloudFormation dynamic
references in MasterUsername and MasterUserPassword during resource creation:
secretsmanagerreferences support whole secret strings, JSON keys, version stages, and version IDs.ssmreferences acceptStringandStringListparameters, using either the latest value or an explicit positive version.ssm-securereferences require aSecureStringparameter and are supported only forMasterUserPassword, matching the AWS resource-property allowlist.
Dynamic-reference expansion is currently scoped to these RDS credential properties.
Account-Aware Provisioning
Resources provisioned by CreateStack / UpdateStack land in the caller's account namespace
(determined from the request's access key — see Multi-Account Isolation).
Deleting the stack removes them from that same account.
Deletion Policies
A resource's DeletionPolicy
attribute is honored on DeleteStack and on the rollback of a failed CreateStack:
| Value | DeleteStack |
Rollback of the create that made the resource |
|---|---|---|
Delete (default) |
deleted | deleted |
Retain |
kept | kept |
RetainExceptOnCreate |
kept | deleted |
A kept resource is reported as DELETE_SKIPPED in DescribeStackEvents and does not fail the
deletion — the stack still reaches DELETE_COMPLETE while the resource keeps existing. This also
lets a stack owning a non-empty S3 bucket be deleted, since the bucket is never touched.
Deviations from AWS to be aware of:
Snapshotdeletes the resource without taking a snapshot; floci has no snapshot support for the types AWS allows it on.- Every resource defaults to
Delete. AWS instead defaultsAWS::RDS::DBCluster, andAWS::RDS::DBInstancewithout aDBClusterIdentifier, toSnapshot. - Unrecognized values are treated as
Delete. - An update that removes a resource from the template does not delete it (or consult its policy);
only the new template's resources are provisioned. AWS applies
DeletionPolicyto update-time removals as well. - After
DeleteStackcompletes, a retained resource'sDELETE_SKIPPEDrecord is only visible throughDescribeStackEventsfor the deleted stack, notDescribeStackResources. UpdateReplacePolicy, and theRetainExceptOnCreaterequest parameter ofCreateStack/UpdateStack, are not implemented.
StackSets
StackSets deploy a single template into many target accounts and regions:
export AWS_ENDPOINT_URL=http://localhost:4566
# 1. Create the stack set (in the administration account)
aws cloudformation create-stack-set \
--stack-set-name my-set \
--template-body file://template.yml \
--endpoint-url $AWS_ENDPOINT_URL
# 2. Create instances in two target accounts
aws cloudformation create-stack-instances \
--stack-set-name my-set \
--accounts 222222222222 333333333333 \
--regions us-east-1 \
--endpoint-url $AWS_ENDPOINT_URL
# 3. The resources materialize in each target account's namespace
aws cloudformation list-stack-instances \
--stack-set-name my-set \
--endpoint-url $AWS_ENDPOINT_URL
CreateStackInstances drives the single-stack engine once per (account, region) pair, provisioning
each instance's resources into that target account's namespace — so a queue named orders deployed
into accounts 222222222222 and 333333333333 exists independently in each. The stack set, its
instances, and its operation history are recorded in the administration (caller) account.
DeleteStackInstances removes instances and their resources, unless RetainStacks=true, which
detaches the instances from the stack set but leaves their underlying stacks and resources in place.
A stack set must be empty before DeleteStackSet.
A CreateStackInstances / UpdateStackSet operation reports FAILED if any of its instances fails
to deploy (the instance is marked INOPERABLE), so polling DescribeStackSetOperation reflects real
provisioning outcomes rather than always returning SUCCEEDED.
Configuration
| Variable | Default | Description |
|---|---|---|
FLOCI_SERVICES_CLOUDFORMATION_ENABLED |
true |
Enable or disable the service |
Examples
export AWS_ENDPOINT_URL=http://localhost:4566
# Validate a template
aws cloudformation validate-template \
--template-body file://template.yml \
--endpoint-url $AWS_ENDPOINT_URL
# Deploy a stack
aws cloudformation create-stack \
--stack-name my-stack \
--template-body file://template.yml \
--parameters ParameterKey=Env,ParameterValue=dev \
--endpoint-url $AWS_ENDPOINT_URL
# Check status
aws cloudformation describe-stacks \
--stack-name my-stack \
--endpoint-url $AWS_ENDPOINT_URL
# Watch events
aws cloudformation describe-stack-events \
--stack-name my-stack \
--endpoint-url $AWS_ENDPOINT_URL
# Update
aws cloudformation update-stack \
--stack-name my-stack \
--template-body file://template.yml \
--endpoint-url $AWS_ENDPOINT_URL
# Delete
aws cloudformation delete-stack \
--stack-name my-stack \
--endpoint-url $AWS_ENDPOINT_URL
# Create a change set
aws cloudformation create-change-set \
--stack-name my-stack \
--change-set-name my-change-set \
--template-body file://template.yml \
--endpoint-url $AWS_ENDPOINT_URL
# List change sets
aws cloudformation list-change-sets \
--stack-name my-stack \
--endpoint-url $AWS_ENDPOINT_URL
# Describe a change set
aws cloudformation describe-change-set \
--stack-name my-stack \
--change-set-name my-change-set \
--endpoint-url $AWS_ENDPOINT_URL
# Delete a change set
aws cloudformation delete-change-set \
--stack-name my-stack \
--change-set-name my-change-set \
--endpoint-url $AWS_ENDPOINT_URL
Lambda + SQS Event Source Mapping
Deploy a Lambda function wired to an SQS queue as a single stack:
# template.yml
Resources:
MyQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: my-queue
MyFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: my-function
Runtime: nodejs22.x
Handler: index.handler
Role: arn:aws:iam::000000000000:role/lambda-role
Code:
ZipFile: |
exports.handler = async (event) => {
console.log(JSON.stringify(event));
};
MyESM:
Type: AWS::Lambda::EventSourceMapping
Properties:
FunctionName: !Ref MyFunction
EventSourceArn: !GetAtt MyQueue.Arn
Enabled: true
BatchSize: 10
aws cloudformation create-stack \
--stack-name my-lambda-sqs-stack \
--template-body file://template.yml \
--endpoint-url $AWS_ENDPOINT_URL
Dependency ordering
Use !Ref MyFunction (not a plain string) for FunctionName so CloudFormation
provisions the function before the event source mapping.