
August 17, 2026
11 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
AWS CloudFormation: Infrastructure as Code on AWS lets you define entire cloud environments in declarative YAML or JSON templates, eliminating manual console clicks and configuration drift. For teams building production web systems, this means reproducible deployments, version-controlled infrastructure, and consistent environments from development to production. Whether you are provisioning a simple Laravel application stack or a complex multi-tier eCommerce platform, understanding AWS cloud hosting fundamentals alongside CloudFormation is essential for reliable operations.
What is AWS CloudFormation: Infrastructure as Code on AWS and why use it?
AWS CloudFormation: Infrastructure as Code on AWS transforms infrastructure provisioning from manual, error-prone console operations into automated, auditable code artifacts. Instead of clicking through the AWS Management Console to create EC2 instances, RDS databases, VPCs, and security groups, you write a template that describes your desired state. CloudFormation then handles the orchestration, dependency resolution, and resource creation in the correct order.
In my experience working on production Laravel applications deployed to AWS, the shift to CloudFormation eliminated an entire class of deployment failures caused by environment inconsistencies. When every environment is defined by the same template, "works on my machine" problems disappear. The template becomes the single source of truth for what infrastructure exists, how it is configured, and how components relate to each other.
The core value proposition extends beyond automation. CloudFormation provides built-in change sets that preview modifications before applying them, stack policies that prevent accidental deletion of critical resources, and cross-stack references that enable modular architecture. For Nepal-based businesses evaluating cloud hosting options, CloudFormation reduces operational overhead significantly compared to manually managed infrastructure, even when team size is small.
How do you write your first AWS CloudFormation YAML template?
Writing effective CloudFormation templates requires understanding the YAML structure, resource types, and intrinsic functions. Start with a minimal viable template and expand incrementally rather than attempting to model everything at once.
Basic template structure and required sections
Every CloudFormation template includes these sections:
- AWSTemplateFormatVersion — specifies the template format (use
2010-09-09) - Description — human-readable explanation of what the stack provisions
- Parameters — input values that make templates reusable across environments
- Resources — the only required section; defines AWS resources to create
- Outputs — values returned after stack creation (endpoints, IDs, ARNs)
AWSTemplateFormatVersion: '2010-09-09'
Description: Laravel application stack with RDS MySQL
Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, production]
Default: dev
DBPassword:
Type: String
NoEcho: true
MinLength: 12
Resources:
AppSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow HTTP and SSH
VpcId: !ImportValue SharedVPC-ID
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 10.0.0.0/8
AppDatabase:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceClass: db.t3.micro
Engine: mysql
EngineVersion: '8.0'
MasterUsername: admin
MasterUserPassword: !Ref DBPassword
AllocatedStorage: 20
DBName: !Sub '${Environment}_laravel'
VPCSecurityGroups:
- !Ref AppSecurityGroup
Outputs:
DatabaseEndpoint:
Description: RDS connection endpoint
Value: !GetAtt AppDatabase.Endpoint.Address
Export:
Name: !Sub '${AWS::StackName}-DBEndpoint' Common intrinsic functions you will use constantly
CloudFormation intrinsic functions resolve values at deployment time. Master these five first:
!Ref— returns the primary identifier of a resource or parameter value!GetAtt— retrieves specific attributes from a resource (endpoint URLs, ARNs)!Sub— substitutes variables into strings using${Variable}syntax!ImportValue— references exports from other stacks for cross-stack communication!If/!Equals— conditional logic for environment-specific configurations
A common mistake I have seen on client projects is hardcoding values that should be parameters or imports. Environment names, instance sizes, CIDR blocks, and database credentials should never be static in production templates. Parameterize early to avoid template duplication later.
How does AWS CloudFormation compare to Terraform for AWS infrastructure?
Choosing between CloudFormation and Terraform depends on your team's constraints, existing tooling, and long-term maintenance strategy. Both accomplish infrastructure as code, but their trade-offs differ significantly.
| Criteria | AWS CloudFormation | Terraform |
|---|---|---|
| AWS Integration | Native, immediate support for new AWS features | Provider-dependent, 1-4 week lag for new services |
| State Management | AWS-managed, no state file to protect | Self-managed state file (S3 + DynamoDB locking) |
| Multi-Cloud | AWS only | Any provider with a Terraform provider |
| Language | YAML or JSON only | HCL (domain-specific language) |
| Drift Detection | Built-in, scheduled or on-demand | Requires terraform plan execution |
| Cost | Free (pay only for provisioned resources) | Open-source free; Cloud costs extra |
| Learning Curve | Moderate, AWS documentation comprehensive | Steeper, HCL syntax plus provider nuances |
| Module Ecosystem | AWS-provided modules, smaller community | Massive registry, community modules abundant |
For teams operating exclusively on AWS with no multi-cloud roadmap, CloudFormation removes state file management complexity entirely. There is no risk of corrupted state, no S3 bucket permissions to configure, and no DynamoDB table to maintain for locking. When working on serverless Laravel deployments on AWS, CloudFormation integrates natively with SAM and Lambda without additional abstraction layers.
Terraform wins when you need multi-cloud portability, prefer HCL over YAML, or require advanced features like workspace-based environment isolation. However, for Nepal-based teams already standardized on AWS, CloudFormation's zero-overhead state management often outweighs Terraform's flexibility advantages.
How do you manage CloudFormation stacks in production CI/CD pipelines?
Production CloudFormation usage requires disciplined pipeline integration. Manual aws cloudformation deploy commands work for learning but fail at scale. Automate stack operations through CI/CD with proper safeguards.
Change sets before every update
Never apply stack updates directly in production. Always generate a change set first, review it, then execute. This two-phase approach catches unintended deletions, replacements, and configuration changes before they cause outages.
# Generate change set without applying
aws cloudformation create-change-set \
--stack-name laravel-production \
--template-body file://infrastructure/app-stack.yaml \
--parameters ParameterKey=Environment,ParameterValue=production \
ParameterKey=DBPassword,ParameterValue={{resolve:secretsmanager:prod/db/password}} \
--change-set-name pre-deploy-review-$(date +%Y%m%d-%H%M%S) \
--capabilities CAPABILITY_NAMED_IAM
# Review changes
aws cloudformation describe-change-set \
--stack-name laravel-production \
--change-set-name pre-deploy-review-20260817-143022
# Execute only after approval
aws cloudformation execute-change-set \
--stack-name laravel-production \
--change-set-name pre-deploy-review-20260817-143022 Stack policies to protect critical resources
Stack policies prevent accidental modification or deletion of stateful resources like RDS instances, S3 buckets with data, and Route53 hosted zones. Apply restrictive policies to production stacks immediately after creation.
{
"Statement": [
{
"Effect": "Deny",
"Action": ["Update:Replace", "Update:Delete"],
"Principal": "*",
"Resource": "LogicalResourceId/AppDatabase"
},
{
"Effect": "Allow",
"Action": "Update:*",
"Principal": "*",
"Resource": "*"
}
]
} This policy allows all updates except replacement or deletion of the AppDatabase resource. Even if a template change would trigger database recreation, CloudFormation rejects the update. For legal-tech portals handling sensitive client data, this safeguard prevents catastrophic data loss during routine deployments.
Integrating with GitLab CI for automated deployments
On projects using Deployer 7 and GitLab CI for application deployments, I integrate CloudFormation into the same pipeline. Infrastructure changes trigger on merge requests to the infrastructure/ directory, separate from application code deployments.
infrastructure_validate:
stage: validate
script:
- aws cloudformation validate-template --template-body file://infrastructure/app-stack.yaml
- cfn-lint infrastructure/app-stack.yaml
rules:
- changes:
- infrastructure//*
infrastructure_deploy_staging:
stage: deploy
needs: [infrastructure_validate]
script:
- aws cloudformation deploy
--stack-name laravel-staging
--template-file infrastructure/app-stack.yaml
--parameter-overrides Environment=staging
--no-fail-on-empty-changeset
--capabilities CAPABILITY_NAMED_IAM
environment:
name: staging
rules:
- if: $CI_COMMIT_BRANCH == "main"
changes:
- infrastructure//* What are common CloudFormation pitfalls and how do you avoid them?
CloudFormation's declarative model hides complexity that surfaces during failures. Understanding these failure modes prevents production incidents and reduces debugging time.
Handling circular dependencies and resource ordering
CloudFormation automatically determines resource creation order based on references. However, implicit dependencies can create cycles that fail validation. When Resource A references Resource B's output while B also depends on A, CloudFormation cannot determine which to create first.
Solve this by breaking the cycle with explicit DependsOn declarations or restructuring into nested stacks. For VPC architectures where security groups reference each other, create base security groups first, then reference them in subsequent resources rather than creating mutual dependencies.
Managing secrets without exposing them in templates
Never store passwords, API keys, or tokens directly in CloudFormation templates. Use AWS Secrets Manager or SSM Parameter Store with dynamic references:
Resources:
AppDatabase:
Type: AWS::RDS::DBInstance
Properties:
MasterUserPassword: '{{resolve:secretsmanager:prod/laravel/db-password:SecretString:password}}' This pattern retrieves the secret at deployment time without embedding it in the template. The resolved value never appears in stack events, change sets, or template artifacts stored in version control. For projects requiring security best practices, this separation is non-negotiable.
Dealing with stack deletion failures
Stack deletions fail when resources cannot be removed automatically. Common causes include non-empty S3 buckets, RDS instances with deletion protection enabled, and ENIs attached to running instances. Before deleting production stacks, verify retention policies and backup requirements.
Set DeletionPolicy: Retain on stateful resources to preserve them during stack deletion. This allows safe stack teardown while keeping databases and storage intact for migration or recovery. Without this policy, a mistaken stack deletion can cause irreversible data loss.
Template size limits and nested stack strategies
CloudFormation templates have a 1 MB size limit (512 KB for direct API calls). Complex architectures exceed this quickly. Split large templates into nested stacks or use modules (available in CloudFormation Registry since 2024).
Nested stacks communicate through parameters and outputs. Keep parent templates focused on orchestration while child templates handle specific concerns (networking, compute, data layer). This modular approach also enables team ownership boundaries where different teams maintain separate stack components.
How do you implement drift detection and ongoing stack governance?
Infrastructure drift occurs when live resources diverge from template definitions due to manual console changes, emergency fixes, or external automation. Undetected drift causes deployment failures and makes templates unreliable as source of truth.
Scheduled drift detection scans
Enable drift detection on production stacks and schedule regular scans. CloudFormation compares actual resource configurations against template definitions and reports discrepancies.
# Initiate drift detection
aws cloudformation detect-stack-drift \
--stack-name laravel-production
# Check detection status
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id abc123-def456
# View drifted resources
aws cloudformation describe-stack-resource-drifts \
--stack-name laravel-production \
--stack-resource-drift-status-filter MODIFIED DELETED Schedule weekly drift scans via EventBridge triggering a Lambda function that reports results to Slack or email. Address drift immediately rather than accumulating technical debt. On legal-tech platforms where compliance requires documented infrastructure states, drift detection provides audit evidence.
Tagging strategy for cost allocation and governance
Implement consistent tagging from day one. Tags enable cost allocation, access control, automation targeting, and compliance reporting. Define a tagging standard covering environment, project, owner, cost center, and data classification.
Use CloudFormation stack-level tags that propagate to all resources automatically. Override individual resource tags only when necessary. Inconsistent tagging creates blind spots in cost analysis and makes automated governance impossible.
Conclusion
AWS CloudFormation: Infrastructure as Code on AWS provides production-grade infrastructure automation for teams committed to the AWS ecosystem. The declarative model, native service integration, and managed state eliminate significant operational complexity compared to external tools. Start with small, focused templates, enforce change sets and stack policies from the beginning, and integrate stack operations into your existing CI/CD workflows rather than treating infrastructure as a separate concern.
For teams evaluating whether to adopt CloudFormation or needing assistance migrating existing manual infrastructure to code, reach out to discuss your specific requirements. Production infrastructure decisions benefit from experienced perspective tailored to your operational constraints and growth trajectory.

