Asynchronous messages - when are the messages delivered/handled?

I was wondering if sending asynchronous message to other Erlang node means that the calling function returns before the message is actually delivered to the remote node, or when the message is delivered to the remote node but may or may not be handled immediately.

I was examining the erpc:cast function and noticed that it uses the spawn_request/5 function to send the message with the option {reply, no}. However, after reviewing the documentation, I am still uncertain if the message will be delivered to the node later or if it is already delivered when the function returns.

For example, is it possible for message “B” to be delivered before message “A” to the remote node in the following code?

erpc:cast(node, fun() -> gen_server:call(server, {message, "A"}) end),
erpc:cast(node, fun() -> gen_server:call(server, {message, "B"}) end),

Once a message is sent (by ! or cast), there is no coupling between the execution of the sending process with the delivery or handling of that message. So to answer your question, no you cannot assume that the message has been delivered (or handled) when the send returns.

If you need for that to be the case, you should use a call type API. Those attach a return address to the message and use a protocol that waits for a reply (or timeout) before they return.

In your second question, the erpc server on the receiving node will receive the funs in the order given, but you don’t know if those funs will be evaluated in the same order, concurrently, interleaved, or what. So yes "B" might be received before "A". (The erpc documentation contains several " You cannot make any assumptions about the process that will perform the apply()." notes/warnings.)

I wonder if your questions are due to your use of erpc:cast/2 to call gen_server on the remote node. gen_server can call process on remote nodes all by itself, you don’t need erpc for that.

1 Like

Thank you for your response. My primary issue is related to the order of messages sent to the remote server. I use the erpc module for this purpose.

Currently, I am not concerned about the responses; however, the order in which the messages are received is crucial to me. I am trying to avoid using because I do not want to block the caller, as it may take a long time to generate a response. Nevertheless, I need to ensure that the messages are delivered in the same order they are sent from the initial node to the remote.

From the initial node or initial process? If the messages are all sent from the same sending process to the same receiving process (whether local or remote) then they will be received in the order they’re sent. If they’re sent from different processes then you may need a local intermediary to impose order.

1 Like

Thank you; this is what I wanted to know. I can still use the cast and maintain the order of messages if they are sent from the same process to the same process on the remote node.

If we’re still talking in the context of erpc:cast, I’m not sure this turned out all clear.

As @alfetahe said, erpc:cast calls spawn_request (with option {reply, no}) to asyncronously spawn a process at a remote node. Assuming that the calls to erpc:cast are made from the same process, ordering guarantees end right there in the sense that one call to erpc:cast came before another. The processes may be spawned at the remote node instantly, later, or not at all, in the same order as the erpc:cast (and the resulting spawn_request) calls or not. Even if they are spawned at the remote node in the same order as the erpc:cast calls, being separate processes the function or MFArgs they are given to execute may be executed in the same order or not.

The story is different when one existing process X sends two (or more) messages to another existing process Y on the same or another node. Those messages are delivered to Y in the same order as they were sent by X, with the possibility that one or both messages may be lost. The only guarantee here is that, if messages A and B are sent in that order from process X to another process Y, B won’t arrive before A, or conversely A won’t arrive after B.


Do I understand correctly that using the erpc module spawns a new process on the remote node, which means I can’t guarantee message order when sending cast messages.

Regarding regular messages sent directly to a process on a local or remote node, I can guarantee message order if the messages are being sent from the same process X to the same process Y on the remote node.


 {remote_server, 'node2@localhost'} ! “Hello word”.

With the code above I can guarantee message order if sent from the same process to the same process on remote node?

1 Like

In a nutshell, yes. But it falls apart even earlier.

(Read together with the Sending Signals paragraph in the Processes chapter in the Erlang System Documentation)
erpc:cast calls spawn_request to create a process to execute the given function or MFArgs on the remote node. spawn_request (and all other kinds of spawn ) sends a spawn_request signal to the spawn service at the remote node. The spawn service is not a single but a group of processes (or rather “entities”, as the doc puts it). So in essence, by sending multiple spawn_requestss, already at this point you (your process) are talking not to a single but several (the spawn service group of) processes at the remote node, and thus the order in which the spawns happen at the remote node may be different from the order in which the spawn_requests were sent from your process. No guarantees here :man_shrugging:

Again in a nutshell, yes. Be aware however that messages (or signals in general) sent over the distribution (ie, between remote nodes) may get lost.

(Read together with the Delivery of Signals paragraph in the Processes chapter in the Erlang System Documentation)
With one process X sending two messages A and B (in that order) to the same other process Y, the message order guarantee is not “A will arrive before B” but “A will not arrive after B”. That is, while it is guaranteed that the messages that do arrive will arrive in the same order as they were sent, it is not guaranteed that all messages will eventually arrive. The messages may arrive at Y like first A and then B, only A (B was lost), only B (A was lost), or neither A nor B (both were lost). The only guarantee is that they will not arrive like first B and then A.