It does not matter if (concurrent) transactions commit in random order. What matters is that:
a) A transaction started after another transaction commits is ordered after it
b) Other transactions observe that order correctly
(Technically a implies b here, but I am stating them both for clarity.)
In order to preserve those invariants, the message version (timestamp) must match the commit order. Using a counter (carefully) in Postgres accomplishes that. Using the node’s clock does not.
If the timestamps do not match the commit order, another process will observe messages out of order or miss them entirely (depending on your implementation). If message 1 commits at t=100, and then message 2 commits at t=200, and then message 3 commits at t=150, an observer could observe [m1, m2]
and then observe [m1, m3, m2]
.
That is very bad. It means that when we read a message there is no way to know if another message came before it, which means we must process messages out of order.
If we process messages out of order we could be susceptible to all sorts of issues, like for example the New Enemy problem.
Imagine we have something like an s3 bucket, implemented on top of our message queue. A user sets the bucket to private, waits for confirmation (commit), and then uploads sensitive medical data.
If a client were to observe those messages out of order, it could expose the private data publicly, which would be catastrophic.