A **template** is the declarative spec for a stack. It's a text file (YAML or JSON) that describes **what AWS resources you want and how they relate** — not how to create them. CloudFormation reads the template and figures out the rest. ## The mental model — the meal analogy | Thing | Role | |-------|------| | **Template** | The recipe (text, edit it freely, copy it, share it, version-control it) | | **Stack** | The cooked meal (the deployed instance, CFN-managed, has a state) | | **Resources** | The food (the actual EC2 instances, S3 buckets, etc.) | The recipe doesn't change when you cook from it. You can cook the same recipe into many meals. You can edit the recipe and re-cook to update what's on the plate. ## What a template is, concretely A text file (`.yaml`, `.json`, or `.txt`), typically tens to thousands of lines, with up to **nine top-level sections** (covered in [[CFN Template Structure Nine Sections]]). Only `Resources` is required: ```yaml AWSTemplateFormatVersion: 2010-09-09 Description: A web server Parameters: InstanceType: Type: String Default: t2.micro Resources: WebServer: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType ImageId: ami-0abcdef1234567890 Outputs: ServerId: Value: !Ref WebServer ``` That's a complete, valid template. CFN can deploy it as a stack. ## Declarative, not imperative This is the key distinction from a shell script. A **shell script** says: "Run `create-vpc`, then `create-subnet`, then `create-security-group`, then `run-instances` with these IDs from the previous calls." A **template** says: "I want a VPC, two subnets, a security group, and an instance. The instance uses the security group. The subnets live in the VPC." CFN reads the template, walks the references (`!Ref`, `!GetAtt`), builds a **dependency graph**, and figures out: - What order to create things (VPC before subnets, subnets before instance) - What can run in parallel (multiple subnets at once) - What to pass where (the security group's physical ID into the instance's properties) You never write the orchestration code. The template is the description; CFN is the engine. ## What CFN extracts from a template When you submit a template, CFN parses it into: 1. **A dependency graph** — derived from `!Ref`, `!GetAtt`, `!Sub`, and explicit `DependsOn` declarations. Determines create / update / delete order. 2. **A logical resource set** — the resources you've named (`MyVPC`, `WebServer`) with their types and desired properties. 3. **A parameter contract** — what runtime inputs are required, with their types and validation rules. 4. **A condition logic tree** — boolean expressions controlling which resources/properties materialize. 5. **An output contract** — what values the stack will publish after creation. The stack record (see [[CFN Stack Concept]]) is then built from this parse + the actual provisioning results. ## What a template is NOT - **Not executable.** You can't "run" a template. You hand it to CFN, which runs it on your behalf. - **Not stateful.** The template doesn't know whether it's been deployed. State lives in the stack. - **Not coupled to a stack.** The same template can deploy as `webapp-dev`, `webapp-staging`, `webapp-prod` — three independent stacks from one file. - **Not validated for semantics.** `validate-template` only checks JSON/YAML syntax. It does NOT check whether your AMI exists, your VPC has capacity, or your IAM permissions allow the operation. Those errors only surface at create time. - **Not a deployment artifact in the CI sense.** A template doesn't get "released" or "promoted" — those are deployments of the template, each producing or updating a stack. ## Where templates live Three places CFN can read from: 1. **Local file** — passed via `--template-body file://app.yaml` (size limit: ~51 KB) 2. **S3 bucket** — passed via `--template-url https://...` (size limit: 1 MB; required for large templates) 3. **Git repository** — via Git sync, CFN watches a branch and triggers stack updates on commit Most teams keep templates in Git for review/history, then sync to S3 for deployment. ## One template, many stacks The reuse pattern that makes templates powerful. The same `app.yaml` can produce: ```bash aws cloudformation create-stack --stack-name app-dev --template-body file://app.yaml --parameters ParameterKey=EnvType,ParameterValue=dev aws cloudformation create-stack --stack-name app-prod --template-body file://app.yaml --parameters ParameterKey=EnvType,ParameterValue=prod aws cloudformation create-stack --stack-name app-eu --template-body file://app.yaml --parameters ParameterKey=EnvType,ParameterValue=prod --region eu-west-1 ``` Three stacks, three sets of resources, one template. Differences come from `Parameters` and `Conditions` (see [[CFN Conditions Boolean Logic]]). The template stays under one source of truth in version control. ## A useful summary > The template describes **what should exist**. The stack tracks **what does exist**. CloudFormation reconciles the two. That reconciliation — figuring out the diff between desired and actual — is what stack updates, change sets, and drift detection are all built on. ## Related - [[CFN Stack Concept]] - [[CFN Template Structure Nine Sections]] - [[CFN Template Format JSON vs YAML]] - [[CFN Ref vs Fn-GetAtt]] - [[CFN Conditions Boolean Logic]] - [[CFN Change Sets Preview-Execute]]