Deploying Code

From time to time, you will be faced with a decision about how to deploy a file, instance configuration, agents, or even entire applications into an AWS environment (we refer to these collectively as ‘artifacts’ below). This page is intended to be our Fanatical AWS “best practices” and opinions around each option.

Many of these options provide an initial bootstrapping step that can then be used to perform additional work or copy additional files from other locations.

Bake files into AMI

Copy needed artifacts to an EC2 image, create an Amazon machine image (AMI), and rotate instances using the new AMI.


  • Create an instance manually and create an AMI

  • Use tools like Packer to automatically build AMIs


  • No dependence on external sources

  • Fastest instance boot time

  • Guaranteed state

  • Strongly version controlled

  • Can release updates to multiple files simultaneously

  • Allows for testing before deployment

  • Encryption possible


  • Updates require a new AMI be built

  • Storage cost of AMIs

  • May have many AMIs with duplicate artifacts (e.g. one AMI per region)

  • Requires additional management to clean up old AMIs

  • Some artifacts need to be staged before AMI taken (i.e. sysprep style)

  • Some artifacts (e.g. agents) may conflict with user-data/cloud-init

AWS CodeDeploy

Install CodeDeploy agent using one of the methods in this table, then use APIs to drive deployment from GitHub, S3, or another supported Git hosting provider. Embed additional artifacts in the deployment artifact or fetch them during CodeDeploy lifecycle hook execution.


  • Store artifacts in git and deploy them as part of application

  • Fetch artifacts in S3 or another location


  • CodeDeploy offers blue-green and canary deployment options

  • Allows for live deployments of configuration files without rotating AMIs

  • Config files can be tied to application deployments

  • Encryption possible with S3


  • Another agent to maintain and update

  • Secrets should not be stored in git repositories

  • Requires a deploy of application to update configuration files

User Data

Embed scripts in user-data or in cloud-init (called by user data). These scripts can fetch artifacts from S3, embed smaller artifacts directly, or even add package repositories and install packages.


  • Fetch files in S3 on boot

  • Write files directly on boot


  • Fastest ability to update files (just build more instances)

  • Ability to always download the latest versions (e.g. for agents)

  • Customer can deploy secrets without Rackspace needing to be involved

  • S3 can be secured and accessible only from a VPC Endpoint

  • Encryption possible


  • Slows down provisioning of new instances

  • Dependence on external source to boot instance

  • Difficult / slow to debug, as autoscaling may terminate unhealthy instances

  • No guarantee that instances will have same artifact versions

  • Security controls must be managed appropriately, with 3rd party code without review on new versions

Native AWS APIs

Write your application to utilize native EC2 SSM Parameter Store or other AWS storage services to directly retrieve artifacts at runtime.


  • EC2 SSM Parameter Store

  • S3, DynamoDB, etc


  • No need to manage config file deployment

  • Applications can be dynamically updated


  • Significantly more opaque than a file-based method

  • Requires a very good knowledge of the AWS APIs

  • May require a re-architecture of the application

Terraform Module

Terraform offers a template provider that can be used to embed artifacts inline or as separate files. You can then use these artifacts via data sources when building a cloud-init configuration.


  • Keep files in git

  • Embed scripts directly in Terraform file


  • Terraform native functionality to deploy files with dynamic values

  • Allows for collaboration on artifacts in Git

  • Uses cloud-init for cross-platform functionality

  • Less files strewn around various places

  • Easier to pull in dynamic values from other APIs

  • Single place to manage instance configuration


  • Requires co-locating configuration files and Terraform files

  • Inline artifacts make Terraform harder to read; painful escaping of strings

  • Not in the spirit of Terraform or Infrastructure as Code

  • Cannot dynamically update artifacts without applying Terraform again