Message identity and IQueueMessageWithId

The IQueueMessage interface doesn't contain any properties so you can define your message in any way you want. But using IQueueMessage means that the system won't have any knowledge of message identity. The system won't compare two messages to see if they are identical to prevent duplicates in a queue.

If you need to ensure that a queue never contains duplicates of the same message you should instead use the IQueueMessageWithId interface.

The only property that you're forced to have on your message class is the Id property. What the id should be depends on your queue. If you want you can use a combination of values in the implementation of the property. The property is allowed to return null so you can have messages in the same queue where some have identity and others don't.

If we take the SendOrderConfirmationQueueMessage from the example in the Overview we can define it like this instead:

[Queue("send_order_confirmation")]
public class SendOrderConfirmationQueueMessage : IQueueMessageWithId
{
    public string? Id => OrderId;
    public string OrderId { get; set; }
    public string Email { get; set; }
}

By doing this the system will ensure that if we already have a SendOrderConfirmationQueueMessage message for order with id 123 we will never allow duplicates to be enqueued. If someone enqueues it again we'll instead update the existing message rather than adding another one. This is true regardless of which status the message has.

Other queue systems has a separate deadletter queue where failed messages are placed which can allow duplicates to still happen. But if we have a message for order 123 in the Error status and someone enqueues a message with that id the existing message gets updated and the status is set to Pending again. Read more about message statuses here.