Azure Service Bus .NET SDK Deep Dive – Expiry

Explains how messages can expire by associating a time to live with the message, for more posts in this series go to Contents.

There are multiple ways of how messages can “disappear” from a queue. The most obvious one is that a message in the queue was received by a client and successfully acknowledged. There is another one that might be not that obvious and can even be leveraged to create clever designs: It is called message expiry or time to live.

If not specified otherwise queues, topics and subscriptions have a DefaultMessageTimeToLive that is set to TimeSpan.MaxValue, indicating that messages sent to those entities should never expire. Imagine you want to send StockPriceUpdate messages to a stockprice queue. Still, due to the nature of stock prices changes, an update message is only relevant for twenty seconds (for the sake of this example). By creating the queue with a DefaultMessageTimeToLive of twenty seconds, all messages sent to the stockprice queue will be expired/discarded if they are not received within a time window of twenty seconds.

var client = new ServiceBusAdministrationClient(connectionString);
var description = new CreateQueueOptions("stockprice")
    DefaultMessageTimeToLive = TimeSpan.FromSeconds(20)
await client.CreateQueueAsync(description);

Expired messages are only purged and moved to the dead letter queue (more about that concept later) when there is at least one active receiver pulling from the entity; that behavior is by design.

Regardless of the settings on the queue, it is also possible to specify a time to live per message being sent by simply setting the TimeToLive property on the message.

 await using var sender = serviceBusClient.CreateSender(destination);
 var message = new ServiceBusMessage("Half life")
     TimeToLive = TimeSpan.FromSeconds(10)
 await sender.SendMessageAsync(message);

If the TimeToLive property is not set, the DefaultMessageTimeToLive of the entity is applied. If the DefaultMessageTimeToLive on the entity is shorter than the TimeToLive property then the entity time to live overrides the any explicitly set TimeToLive.

The video shows how a message is sent with a TimeToLive set to ten seconds and is never received because the receiver is too busy during that time.

The video shows how nothing is in the queue because the message that was sent was already expired.

TimeToLive either on the message or on the entity is a great concept to implement automatic message expiry of the information transmitted over the message only has a certain lifespan and we want to avoid overloading the receiver with anyway outdated information. Going back to the previous StockPriceUpdate example, if we are sending thousands of those messages to the stockprice queue and the receiver is going down for a short a period of time, the next time it comes up all already outdated messages are purged from the queue and only still relevant messages need to be processed.

Updated: 2021-03-23 to use the new SDK

About the author

Daniel Marbach

1 comment

By Daniel Marbach

Recent Posts