The ApproximateMessageCount metric in Amazon SQS is actually a snapshot of the number of messages in a queue that are not yet deleted, which can be higher than the number of messages your consumers will actually process.
Let’s see this in action. Imagine we have a queue my-processing-queue and a consumer application that’s been running for a bit.
aws sqs get-queue-attributes --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/my-processing-queue --attribute-names ApproximateNumberOfMessages
If we run this command, we might get an output like:
{
"Attributes": {
"ApproximateNumberOfMessages": "150"
}
}
This tells us there are 150 messages currently visible in the queue. Now, let’s say our consumer application is processing messages. We can simulate sending a few more messages:
aws sqs send-message --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/my-processing-queue --message-body "{\"data\": \"new_task_1\"}"
aws sqs send-message --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/my-processing-queue --message-body "{\"data\": \"new_task_2\"}"
If we check ApproximateNumberOfMessages again immediately after sending, we might see:
{
"Attributes": {
"ApproximateNumberOfMessages": "152"
}
}
This metric is critical because it’s your primary indicator of how much work is waiting to be done. A consistently high ApproximateMessageCount means your consumers aren’t keeping up with the rate at which messages are being produced, leading to increased latency for your application’s tasks. Conversely, a rapidly dropping count indicates your consumers are actively processing and clearing the queue.
The core problem SQS solves here is decoupling message producers from message consumers. A producer can send messages without waiting for a consumer to be ready, and a consumer can process messages at its own pace. ApproximateMessageCount bridges this gap by providing visibility into the backlog.
Internally, when a consumer receives a message using ReceiveMessage, SQS makes that message invisible to other consumers for a specified visibility timeout period. During this time, the message is still counted in ApproximateMessageCount. If the consumer successfully processes the message and deletes it using DeleteMessage, the count decreases. If the visibility timeout expires before the message is deleted, SQS makes the message visible again, and it can be re-processed. This "at-least-once" delivery mechanism is why the count can sometimes be misleading.
The levers you control are primarily:
- Consumer Scaling: The number of consumer instances you run. More consumers generally mean a lower
ApproximateMessageCount. - Visibility Timeout: The duration a message remains invisible after being received. A shorter timeout allows faster reprocessing if a consumer fails, but can increase processing load if messages are frequently re-delivered. A longer timeout gives consumers more time but might mask actual processing failures if the timeout is too generous.
- Batching: Consumers can receive messages in batches (
MaxNumberOfMessagesinReceiveMessage) to improve throughput, which directly impacts how quickly theApproximateMessageCountdecreases.
The ApproximateMessageCount metric reflects messages that are either waiting to be received or are currently received by a consumer but not yet deleted (i.e., they are within their visibility timeout). If you have a high ApproximateMessageCount and your consumers are actively polling and receiving messages, it means many messages are in the visibility timeout period, and you might need to either increase the number of consumers or decrease the visibility timeout if messages are being processed quickly.
The next concept you’ll likely encounter is ApproximateNumberOfMessagesVisible, which is a more precise indicator of messages that are ready to be processed, excluding those currently in a visibility timeout.