By default Cloudformation will delete a resource when the stack is deleted or resource is removed
from template. Resources can also be replaced, that is deleting existing resource after new is
created during stack update. When you have persistent data stored into database or disk, you
would want to retain rather then delete. Resource retention can be controlled with
What is DeletionPolicy?
DeletionPolicy is an optional attribute you can use to preserve a resource when it would otherwise be deleted due to stack deletion or update where resource is removed from the template. For EBS volumes, databases and Elastic caches, you can also take a final snapshot before resource deletion.
Use-cases for DeletionPolicy
The Main use-case for
DeletionPolicy attribute is to protect stateful resources being deleted
during stack update or deletion.
Secondary use-case is, if you are not planning to maintain resources via Cloudformation stacks,
DeletionPolicy when creating stack and resources, with pre-defined standard architecture,
and then delete the stack but retain resources it created.
Retail or RetainExceptOnCreate?
DeletionPolicy can have 4 different values, depending what you want to happen when resource
is about to be deleted.
Deleteis the default when you don’t specify ´DeletionPolicy` and resource will be deleted.
Retainwill skip the deletion and resource will remain as-is, except it isn’t part of cloudformation stack any longer.
Snapshotwill take final snapshot before deleting the resource. This option is available only for EBS volumes, Elastic caches and certain databases.
RetainExceptOnCreateis the latest addition that works the same way as
Retainbut won’t retain resource if initial stack creation or resource creation at stack update ends with rollback.
So, should you use
RetainExceptOnCreate? I really don’t see any reasons why Retain
would be better than RetainExceptOnCreate. Original
Retain is preserved for backwards compatibility
RetainExceptOnCreate does cleanup after a failed stack creation or update automatically.
Even when you are using stacks just to create resources, but not maintaining them through updates,
this retains resources because stack deletion is separete operation after successful creation.
If you read above carefully, you noted I said “deleted”. But resources can also be replaced, i.e.
creating a replacement and then deleting the original. During stack updates it can be difficult
to see beforehand what changes will trigger resource replacement. Creating a change set
will reveal this, so you can avoid doing it accidentially, but sometimes replacements just can not be
avoided and then
UpdateReplacePolicy is the way to retain your data.
UpdateReplacePolicy has the same options as
DeletionPolicy, except you can not use
as it doesn’t make sense for resource updates.
How to apply DeletionPolicy (and UpdateReplacePolicy)?
The Most simple way, when you need just an on/off -switch, is using
Ability to include functions in policies was introduced in
transform, but it is now part of standard Cloudformation and transform is no longer required.
# Oct12th 2023, AWS::LanguageExtensions is no longer needed for # intrinsic functions in DeletionPolicy or UpdateReplacePolicy. # Transform: AWS::LanguageExtensions Parameters: Environment: Type: String Default: dev AllowedValues: - dev - test - prod Description: Environment type Conditions: IsProd: !Equals [ !Ref Environment, "prod" ] Resources: MyDB: Type: AWS::RDS::DBInstance DeletionPolicy: !If [ "IsProd", "RetainExceptOnCreate", "Delete" ] UpdateReplacePolicy: !If [ "IsProd", "Retain", "Delete" ] Properties: ...
If you need more than on/off -switch, e.g. there are more than one environment where you would want to retain resources, it might be easier to create a map than maintain complex conditions clauses.
# Oct12th 2023, AWS::LanguageExtensions is required for FindInMap default value feature. Transform: AWS::LanguageExtensions Parameters: Environment: Type: String Default: dev Description: Environment type, e.g. dev, test, stage, prod Mappings: Policies: stage: Delete: RetainExceptOnCreate Update: Retain prod: Delete: RetainExceptOnCreate Update: Retain Resources: MyDB: Type: AWS::RDS::DBInstance DeletionPolicy: !FindInMap [ Policies, Environment, Delete, DefaultValue: Delete ] UpdateReplacePolicy: !FindInMap [ Policies, Environment, Update, DefaultValue: Delete ] Properties: ...
Above would allow you to use freeform environment names and retain resources when environment is
prod. In all other environments, resources will be deleted. Note that
FindInMap is also part of
How to apply DeletionPolicy for all resources in template?
Problem with above solution, is you need to add policy attribute(s) for every resource in template individually. It would be nice if there was a switch in Cloudformation API you could turn on and set Retain(ExceptOnCreate) policy for every resource. Unfortunately there isn’t such a thing, but you could get close to this by building a custom transformation.
I will leave the implementation of such transform for reader as homework, but if you do this, please drop me a note where can I find your implementation ;-)