Hacker News new | past | comments | ask | show | jobs | submit login

Here are the docs on idempotency: https://docs.differential.dev/advanced/idempotency/



You mentioned elsewhere that you're still finding the right wording for the product and its benefits. Fair enough. Personally, I think you should probably stop referring to this as idempotency. Maybe describe it as a retry policy, or as a choice between at-least-once and at-most-once. I expect most people with knowledge of - and respect for - distributed systems theory will be completely put-off by this wording.

In distributed systems, the reason idempotency is such a Big Deal™ is that it can be combined with at-least-once delivery to achieve exactly-once semantics. This isn't that. What you're describing as idempotency has the potential to mislead users, especially since you use examples like credit card processing.


Thanks for the thoughtful reply.

You might be on to something here:

> Maybe describe it as a retry policy, or as a choice between at-least-once and at-most-once

and we will consider changing it because I agree that conflating the concepts (or the appearance thereof) is not worth diluting the other parts of the offering.

I still struggle to find the difference between this approach and the likes of Stripe [1] and Temporal [2] because in practice, it yields the same result.

[1] https://docs.stripe.com/api/idempotent_requests

[2] https://www.restack.io/docs/temporal-knowledge-temporal-io-i...


One difference is that you are specifically creating distributed systems middleware, where your audience is going to be using your product in the implementation of a system of their own, and is more likely to understand the terminology and wish to know the exact guarantees and trade-offs being provided.

I find both those comparisons are apples to oranges:

1. Temporal does not claim, on that page, to be able to automatically make your calls idempotent. Instead, it is explaining how you - as the user - can and should write your activities to be idempotent. Take the payment code snippet: you can't just wrap `ExternalPaymentAPI.Process(paymentId, amount)` in an idempotency provider. You have to implement specific idempotency logic inside the activity. This is in line with the distributed systems theory of idempotency.

2. In these docs, Stripe describes an interface for achieving idempotency as an external caller. Since Stripe control the implementation of their own system, it is certainly possible that they have implemented their operations in a way that is truly idempotent. What your docs describe - the ability to make arbitrary operations idempotent by wrapping them - is simply not possible.

I wonder whether you're focusing on the idempotency key as the thing that is wrong here. There is nothing wrong with idempotency keys themselves - they are a great way for APIs to provide idempotency. The problem is that this guarantee can't be provided by a wrapper layer, it requires the operation itself to be written in an idempotent way. This is an example of the age old "end-to-end principle" from networks class.


Ok, yes - I'm with you.

I now realise how this statement could be misleading.

> To mark a function as idempotent, simply wrap it with the idempotent function.

When initially writing it, I thought it was a "given" that the wrapped functions are the responsibility of the developer. Now I realise this can also be interpreted as "we make your functions idempotent".

Thanks for the detailed breakdown. We will work on the docs to make it clearer.


If that was the assumption, then this whole thing makes even less sense. If your operation is already idempotent in its implementation, then wrapping it with this function is the last thing you'd want to do. By introducing at-most-once semantics on top of the call, it would defeat the point of making the operation idempotent to begin with.

The scenario where you'd want to use this `tryOnce` policy is probably the following:

1. You have an operation that is not idempotent and can't be made idempotent, for whatever reason.

2. You would prefer the failure mode of that operation to be that the effect doesn't take place, rather than that the effect takes place more than once.

BTW, you don't need to have an answer for everything. I don't think there has been any miscommunication or misunderstanding of the docs. I think people in this thread, including myself, have accurately identified that you haven't fully thought some of this stuff through. That's fine and normal for a product in this stage, but not being willing to admit it is less of a good sign. Good luck with the startup.


> If your operation is already idempotent in its implementation

No, this is not at all what I meant. I don't think there's any value in introducing at-most once semantics to an already idempotent function.

I'm definitely not trying to have an answer for everything. But I guess we can leave it at that, at this point.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: