Вообще то есть "best practices". Да, это использовать Load Balancer и Auto Scaling.
А вот AMI можно приготовить или как говорят на западе в этом контексте "to bake the image". Есть очень удобный тул от Hashicorp -
Packer. С его помощью можно сделать готовый AMI со свежей версией вашего проекта. Далее создаете новый ASG с этим AMI.
Делаем релиз:
Старый AS оставляем 100% и плавненько увеличиваем капасити нового AS, доходим до количества инстансов 100%. Трафик идет и на старые инстансы и на новые(со свежим кодом), смотрим логи, всё в порядке? Новая версия встала как надо? Тогда уменьшаем количество инстансов старого AS до нуля. Релиз закончился. Если что то не так с новой версией можно легко ролбекнутся на старую, и даже спустя время(час, день, неделя) можно сделать удобный и четкий роллбек на любой ваш релиз, благо все ASG у вас есть, капасити нужного релиза увеличиваем, не нужного уменьшаем. Это и есть zero downtime deployment. Кстати таким макаром удобно делать A/B тестирование.
P.S создавать AS тоже можно делать удобно:
terraform