Tarmac

How to Search an SQS Queue for a Message

AWS SQS has no search API. Find a message by ID, body text, or attribute with the AWS Console, the AWS CLI, sqs-grep, or a local cache you can search.

You cannot search an SQS queue in place. SQS has no search API and no way to get one message by its ID. The only way to read a message is to receive it.

So every method on this page works the same way. Receive messages, look through them on your side, then give them back. The methods differ in how many messages you can look through, what you can match on, and what you keep afterward.

What a receive costs

Know this before you start, because it applies to every method below.

  • The message is hidden. A received message stays invisible for the visibility timeout. Your real consumers cannot receive it until the timer ends or you release it.
  • The receive count goes up. Each receive adds one to ApproximateReceiveCount. If the queue has a redrive policy, a message that goes past maxReceiveCount moves to the dead-letter queue. Searching a queue many times can push messages there.
  • You see a sample. A standard queue returns messages in no fixed order. An empty response does not prove the queue is empty.
  • In-flight messages have a limit. A queue can hold at most 120,000 messages that were received but not yet deleted. A long scan can reach it, and then your consumers get no new messages either.

If the message you want is on a busy production queue, keep the visibility timeout short and release what you received when you are done.

Option 1: The AWS Console

Use this to look at a few messages on a small queue.

  1. Open the queue in the SQS console.
  2. Choose Send and receive messages.
  3. Choose Poll for messages.
  4. Open each message to read its body and attributes.

The console polls up to 10 messages at a time. It has no search box, so you open messages one dialog at a time and read them. Everything you poll counts as a receive, with the costs above, and stays hidden for the queue's default visibility timeout.

Option 2: The AWS CLI and jq

Use this to scan a few hundred messages for a string. The script receives in batches, saves every message to a file, and holds them invisible for 5 minutes so the same messages do not come back during the scan.

QUEUE_URL="https://sqs.us-east-1.amazonaws.com/123456789012/orders"
: > received.jsonl

for i in $(seq 1 50); do
  aws sqs receive-message \
    --queue-url "$QUEUE_URL" \
    --max-number-of-messages 10 \
    --visibility-timeout 300 \
    --wait-time-seconds 1 \
    --message-system-attribute-names All \
    --message-attribute-names All \
    --output json | jq -c '.Messages[]?' >> received.jsonl
done

Search the file. This matches the ID, body, and attributes, and ignores case:

grep -iF "ord-42" received.jsonl | jq -s 'unique_by(.MessageId) | .[] | {MessageId, Body}'

Release everything you received, so your consumers get the messages now instead of in 5 minutes. A message received twice has a new receipt handle each time, and only the latest one works:

jq -rs 'group_by(.MessageId) | map(last.ReceiptHandle) | .[]' received.jsonl |
  while read -r handle; do
    aws sqs change-message-visibility \
      --queue-url "$QUEUE_URL" \
      --receipt-handle "$handle" \
      --visibility-timeout 0
  done

Adjust the loop count to the queue depth. Each pass receives at most 10 messages. If the scan takes longer than the visibility timeout, the first messages come back and you receive them again.

Option 3: sqs-grep

sqs-grep is an open-source command-line tool built for this job. It scans a queue for messages that match a pattern, and it can also delete, copy, or move the matches. It holds each batch invisible only for a short time while it scans, so messages go back to your consumers soon after. It has the same receive costs as the script above. Add --outputFile to save the matches, then search that file again with --inputFile instead of the queue.

Option 4: Fetch once, search locally with Tarmac

Use this when you search the same queue more than once, or when you need to filter on JSON fields.

Tarmac is a desktop client for SQS on macOS and Windows. It receives messages into a local cache on your machine. After that, every search runs against the cache, not the queue. A search adds no receive, no receive count, and no hidden time.

  1. Select the queue.
  2. In the Operations panel, set Count to how many messages to receive (1 to 10,000) and Visibility (min) to how long to hold them.
  3. Press Fetch Messages.
  4. Search with ⌘/Ctrl + F. Search matches message IDs, attribute values, and body text.
  5. Narrow the results with facet filters built from your JSON fields, such as order.status: failed, and a sent-date range.

When you quit, or clear the queue's cache, Tarmac releases every message it still holds by setting the visibility timeout to 0. The cache keeps its copies, so you can search them again tomorrow without another receive. Fetch, search, and release are all in Tarmac Free.

See Search AWS SQS Messages for the search syntax and facet rules.

Compare the options

AWS ConsoleCLI + jqsqs-grepTarmac
Search body textNo, read by handYesYesYes
Filter on JSON fieldsNoWith extra jqRegex onlyYes, facets
Search again without a new receiveNo, poll againYes, in the fileYes, saved matchesYes, in the cache
Releases messages when doneAfter the timeoutWith a scriptShort holdYes

If you search a queue every week

Then the queue is doing a second job as your message history, and it is bad at that job. Messages leave when they are consumed and expire after the retention period. Fix it upstream:

  • Log the message ID and key fields at the producer. Then you search your logs, not the queue.
  • Archive a copy of every message. For example, fan out from SNS to Amazon Data Firehose and store the messages in S3. You can then query them with Athena.

Until then, pay the receive cost once and search a copy.

On this page