Cover image for CloudFormation Tips, Tricks, And Hacks

CloudFormation Tips, Tricks, And Hacks

forstmeier profile image John Forstmeier ・3 min read

At work I spend a lot of time working with AWS CloudFormation. It's a core part of my team's work and forms the backbone of our microservice architecture. I've put together a quick list of some of the slickest features that I'm a fan of that help to make the templates more dynamic/organic assets - they add some spice to the soup.

  1. Conditional resources: by including a Conditions field in any of your template Resources, you can configure the given resource to not/exist depending on a condition that you define in your Conditions section. This can be pretty helpful if you want different resources available in different contexts (e.g. testing vs. development).
  2. Conditional properties: this is similar to #1 above and is similarly useful but focuses on individual properties. For example, AWS::ApiGateway::BasePathMapping provides a BasePath property that you may or may not actually want but AWS requires that it not be set to an empty string. You can combine your condition Fn::If check to have an AWS::NoValue pseudo-parameter that will not create that optional property if the statement evaluates as such.
  3. Nested stacks: separating different resources (particularly in a microservice) is much more easily done by including "parent" stacks to orchestrate the "child" stack microservices. In the Resources, an AWS::CloudFormation::Stack can be defined which adds the "child" to the "parent". Outputs can be shared between the stacks and parameters can be passed directly to the children via the Parameters property. I think of it like function scopes.
  4. Named resources: avoid naming resources and instead refer to their logical names or ARNs where at all possible - explicitly naming them typically results in being unable to launch multiple instances of that resources in the same account as the names will collide (e.g. testing in different stages); a randomly generated ARN won't have this problem but you do need to use Ref or Fn::GetAtt to reference it.
  5. Intrinsic functions: using these liberally can really improve the flexibility and dynamism of your template.
  6. Custom resources: these are pretty nifty and can be used to automate specific tasks not available in normal template operations, for example loading/backing up databases or Elasticsearch indexes; however, I did find these to be a bit tricky to set up and if you get it wrong they can hang for an hour before finally rolling back.
  7. Descriptions: please, please, please use the Description attribute wherever you see it - it provides a great deal of context when looking at the console.
  8. Swagger definitions: using this allows you to offload API Gateway-related resource definitions to a separate file if you want, but you should take a look at a prior post of mine regarding the limitations there.

These are a handful of things that I've found pretty slick while working with CloudFormation templates but I'm sure there are plenty more!



markdown guide

Another thing I'd suggest is making sure your resources are tagged. Like the description fields, this help in finding resources related to particular workloads, or organizing things by patterns you use. It's a good habit to get into.


Thank you John for the article, and david for the resource. I never did like 'IaC' but it is really 'IaJSON' :S. Pulumi looks like it will actually be IaC. I hope they add more languages beyond JS and Python.


I agree (from my cursory look at Pulumi); I love the idea of making it more "interactive" than just lots of JSON (YAML would at least be more readable but that choice was not mine lol).

Meh... Once you've gotten to the point of parsing JSON in your head, "readable" is relative (though, YAML templates do mean you can sprinkle your templates with comments).

Who is ever going to need to put comments in code? :sarcasm: The biggest gripe I have about current JSON implementation is no provision for inline comments. Infra-as-Code, let me CODE my infra! Not 'infra as data transport format syntax". #amiright?

That's my biggest bitch. Less so for my own sake than as we add people to the team — many of whom are new to CFn's programming constructs. Especially since some of the constructs are fairly limited, sometimes requiring fairly tortuous logic to string together enough intrinsics (etc.) to achieve the desired results.

I've found myself having to write "here's what all this means" walk-throughs for newer staff-members. Comments could fix some of that.


If you don't like JSON, use YAML. It's available in pretty much all the regions, at this point. Big down-side to converting, though, is if you're making used of many of the dynamism-promoting techniques mentioned by the OP, most of the converters puke all over their shoes.

bad time


I'll definitely have to look into it. I like anything that makes the construction of the infrastructure/resources separate from the business logic code but also retains the flexibility of code.


Down side is, when you make liberal use of these techniques, your use of the CLI becomes aws cloudformation create-stack ... --template-url ... rather than ...--template-body ... (though, if you're using nested stacks, you're already stuffing shit into S3, any way).

That 50KiB temlate size-limit's still a bitch, though. Thank god for --parameters.