Messaging Delivery Guarantees
Orleans messaging delivery guarantees are at-most-once, by default. Optionally, if configured to do retries upon timeout, Orleans provides at-least-once delivery instead.
In more detail:
Every message in Orleans has automatic timeout (the exact timeout can be configured). If the reply does not arrive on time, the return Task is broken with timeout exception.
Orleans can be configured to do automatic retries upon timeout. By default it does NOT do automatic retries.
Application code of course can also choose to do retries upon timeout.
If the Orleans system is configured not to do automatic retries (default setting) and the application is not resending – Orleans provides at-most-once message delivery. A message will either be delivered once or not at all. It will never be delivered twice.
In the system with retries (either by the runtime or by the application) the message may arrive multiple times. Orleans currently does nothing to durably store which messages already arrived and suppress the second delivery. (We believe this would be pretty costly.) So in a system with retries Orleans does NOT guarantee at most once delivery.
If you keep retrying potentially indefinitely, the message will eventually arrive, thus providing at-least-once delivery guarantee. Notice that “will eventually arrive” is something that the runtime needs to guarantee. It does not come for free just by itself even if you keep retrying. Orleans provides eventual delivery since grains never go into any permanent failure state and a failed grain will eventually be re-activated on another silo.
So to summarize: in the system without retries Orleans guarantees at-most-once message delivery. In the system with infinite retries Orleans guarantees at-least-once (and does NOT guarantee at-most-once).
Note: In the Orleans technical report we accidentally only mentioned the 2nd option with automatic retries. We forgot to mention that by default with no retries, Orleans provides at-most-once delivery.