The way I have tried to implement (very likely, shoddily) idempotency is to have each mutation on an external service (say creating a customer in Stripe, corresponding to an account already administered in my database) first check if a customer with that ID already exists, and if not to create it - otherwise use the existing object (Stripe customer in this example).
``` user = Database.get_user(my_user_id)
if (Stripe.customer_exists(user.id) { return Stripe.get customer(user.id) } else { stripe_customer = Stripe.create_customer(user.id, user.email) Database.set_user_property("stripe_customer_id", stripe_customer.id) return customer } ```
The problems here are multiple, but at the very least I see the possibility of very nasty bugs if somehow the `customer_exists` call returns a false negative - this will cause the same customer to be created in Stripe twice (and thus potentially be charged twice). Another, more likely, issue is that between the `Stripe.create_customer` call and the `set_user_property` there may be an unexpected event (service/network goes down, whatever) failing to store the property - leading to a duplicate Stripe customer the next time the above code is executed. On top of that, I find it pretty difficult to reason about a code base chock full of this type of logic (perhaps that is just my personal limitation though!).