AWS Logo
Menu

5 AWS Services, 5 Different Approaches to Idempotence

Comparing idempotence in CloudFormation UpdateStack, AWS Backup StartBackupJob, and EC2, RDS and Aurora Start/Stop

Published May 23, 2025
If your application uses EventBridge, SQS queues, AWS Lambda functions, Step Functions, or other constructs from the realm of modern, "loosely-coupled" software architecture, you can make it faster, simpler, and more reliable by attending to idempotence. There is less overhead, less checking, once you can guarantee that repeating an operation won't change the result. If the AWS operations that underly your application are idempotent, it is even easier to make your own code idempotent.
In the process of writing and refining github.com/sqlxpert/lights-off-aws , a tool to cut costs by temporarily stopping or deleting expensive resources based on cron schedules in resource tags or stack tags, I've become all too familiar with the different ways in which 5 core AWS services approach idempotence. The services were launched at different times, and it shows.
OperationsIdempotence MechanismException, Error CodeToken (Restrictions)
EC2:
StartInstances StopInstancesBuilt-in
RDS:
StartDBInstance StopDBInstanceNot idempotentInvalid…StateFault Invalid…State
Aurora:
StartDBCluster StopDBClusterCheck error message afterInvalid…StateFault Invalid…StateFault
CloudFormation:
UpdateStackSet token beforeClientRequestToken (≤128 letters, numbers, hyphens)
AWS Backup:
StartBackupJobSet token beforeIdempotencyToken (no restrictions)

1. EC2

EC2 is the oldest of the 5 services covered. StartInstances and StopInstances are idempotent. If I try to start a compute instance that is already running, my request succeeds. The dynamic response mentions that the instance was already running at the exact time of my request, in case I need to know.

2. RDS

RDS was built on EC2, but StartDBInstance and StopDBInstance are not idempotent. If I try to start a database that is already running, I get an error. The exception name is InvalidDBInstanceStateFault but the error code is InvalidDBInstanceState — a bug waiting to happen! The only thing the long, mostly static error message doesn't tell me is that the database was already running (available) at the exact time of my request. I don't know whether to ignore the error (because my start request is indeed a harmless repeat) or take it seriously (in case the database is in a bad state and cannot be started). Keep in mind that relying on a separate status check would create a race condition.

3. Aurora

Aurora is RDS's new and improved cousin. StartDBCluster and StopDBCluster feature a consistent exception name and error code, InvalidDBClusterStateFault . More importantly, the dynamic error message mentions that the database was already running (available) at the exact time of my request. Knowingly ignoring the error achieves idempotence after the fact.

4. CloudFormation

CloudFormation predates Aurora. If I add a fixed token, UpdateStack is idempotent: repeated requests succeed and CloudFormation acts only on the first request. ClientRequestToken is limited to 128 alphanumeric characters and hyphens. Because idempotence often applies during a known time interval, and because CloudFormation displays the token in the AWS Console (in the stack events list), a human-readable "extended" ISO 8601-standard time string would be ideal. Instead, we have to settle for the cryptic "basic" form, T1510Z instead of T15:10Z, for example.
Arbitrary lexical restrictions that make token values harder for humans to interpret are frustrating, but there is also a semantic problem lurking below this approach to idempotence. What UpdateStack idempotence case cannot be resolved with a token? Feel free to discuss in the comments. Hint: review the EC2 StartInstances example, above.

5. AWS Backup

AWS Backup is the newest of the 5 services covered. StartBackupJob follows the same approach as CloudFormation UpdateStack , but the token is named IdempotencyToken and no specific limits are placed on length or permitted characters.

Differences, and Why We Care

These 5 AWS services take different approaches to idempotence. EC2, the oldest of the 5, and AWS Backup, the newest, handle idempotence very well. RDS StartDBInstance and StopDBInstance are not idempotent. The Aurora equivalents, StartDBCluster and StopDBCluster , put extra work on the user — and CloudFormation UpdateStack does, too, though there's no warning in the UpdateStack documentation.
If we consider EC2 StartInstances / StopInstances , Aurora StartDBCluster / StopDBCluster and AWS Backup StartBackupJob as examples of three basic approaches to idempotence, which two approaches are semantically equivalent? Would any one approach be sufficient to make all of the operations covered in this article idempotent? If not, what makes one operation or pair of operations special? Feel free to discuss your ideas in the comments.
Inconsistencies are expensive! As AWS users, we have to discover them, sometimes by trial and error, then write extra code to work around them, and then fix the extra bugs that result. Although it's impractical to change existing, widely-used APIs, I hope AWS will standardize its approaches to idempotence in new services and features. I suggest ways to prevent inconsistent software designs and implementations within our own organizations, in the second half of a less technical version of this article, on LinkedIn
 

Comments