Check the queue without consuming a message
Use the installed SQS origin endpoint, signing Region, and existing IAM workload profile with the actual queue URL. Set these placeholders from the application configuration;SQS_ENDPOINT_URL is distinct from the report service’s T9_ENDPOINT_URL.
409 ExplainedNotPerformed preview is not a queue-attribute result or evidence that the queue is missing. Some attributes are approximate, delayed, unavailable, or declared rather than live on particular mappings. Do not infer that a message is absent from one count. Compare the returned queue ARN, account, Region, queue type, and installed target profile before investigating delivery. A ReceiveMessage call is different: it can claim messages and start their visibility timeout, even if the consumer later crashes.
Read the batch response as well as its HTTP status.
SendMessageBatch and DeleteMessageBatch can return per-entry failures after a successful HTTP response. Preserve each entry ID and error code. A service error remains the SDK’s native SQS result; an explanation report records adapter decisions separately. Network or SigV4 failures may leave no report receipt.
Worked case: a job reappears after a slow worker
A worker receivesinvoice-1001, starts a six-minute database task, and sees the same job again. First inspect the queue’s VisibilityTimeout and the receive attempt’s timestamp. If visibility was 120 seconds, a second receive after that interval is expected when the first worker has not deleted or extended the claim. Compare both receipt handles; delete or change visibility using the current handle, following that backend’s rules. A Service Bus mapping caps requested visibility at five minutes and its broker-lock handles do not survive an adapter restart. PostgreSQL mappings store durable handles, but a stale claim still fails. Confirm the selected profile before changing the timeout.
If this is a FIFO queue, record MessageGroupId and MessageDeduplicationId. An in-flight head blocks later messages in its group while other groups can proceed. A repeated send with the same deduplication ID may be suppressed during the documented window; it is not proof that a consumer finished processing. Azure Service Bus has a documented difference in the ID returned for a suppressed send. AWS FIFO terms explain the origin behavior; the FIFO profile states mapping differences.
Do not send the job again to diagnose it. Check the application’s durable job ID and downstream completion first. If the send response was lost, reconcile message and business state before deciding whether a new send is safe. AWS visibility guidance explains why an unacknowledged message can become visible again.
Use a report for a specific request
For a non-executing request check, confirm installed capture support for that operation, then add a signed version-1x-t9-explain control with mode Explain before signing. A completed preview returns 409 ExplainedNotPerformed with a receipt; unsupported capture can return a refusal. ExecuteAndExplain and x-t9-explain: true execute the SQS operation; a preview of ReceiveMessage must not be treated as a claim. Do not use an executing control to replay an uncertain send or delete.
Save the native status, SQS error code, request ID, x-t9-explain-id, and receipt expiry. Read the existing report with T9CloudAdapter.GetExplanation on the install’s published t9 endpoint, SigV4 service t9, published signing Region, and the same report owner’s IAM credentials and session token. The developer CLI can read an existing report without rerunning the queue operation. A receipt does not prove that asynchronous target work finished; inspect report lifecycle and follow asynchronous explanations where applicable.
PostgreSQL-backed queues may eventually include full PostgreSQL plan evidence for qualified operations. Availability depends on the installed version and backend. Plans can expose physical relation names and predicates, are owner-only, and describe a separate committed-state estimate. They do not prove a message was delivered, deleted, or dead-lettered. Use the queue attributes, exact message identity, native result, and downstream state for those conclusions.
Worked comparison: send one job through different backends
Suppose the application sendsinvoice-1001 once and receives a successful SendMessage response. Keep that native response’s message ID and report receipt. The same SQS operation can map to a PostgreSQL insert, a Service Bus broker send, or a Pub/Sub publish. The Standard and FIFO profiles identify which mapping is installed; a backend supported for Standard is not automatically supported for FIFO.
Retrieve the existing send report
Use the report receipt from the original send, rather than sending the message again. Keep the origin SQS endpoint separate from the publishedt9 report endpoint:
T9CloudAdapter.GetExplanation for service t9. It prints the rendered report, sends no SQS operation and does not acknowledge the report. With a direct SDK client, first decode the outer AWS JSON response’s body string, then inspect the rendered JSON’s facts. A new assumed-role session cannot read the original session’s report.
If collection is still in progress, read the same report with bounded backoff. Omit minimumVersion until a positive revision exists. Export any needed evidence before acknowledgment or the fixed expiry in x-t9-explain-expires-at; reads do not renew the default 24-hour retention. See existing-report retrieval.
PostgreSQL: inspect the insert estimate
PostgreSQL plan reporting is planned, October 25, 2026. Owner: Tensor9 Cloud Adapter team. The Standard PostgreSQL paths being qualified include
SendMessage, ReceiveMessage, DeleteMessage and ChangeMessageVisibility. The example below focuses on statement code sqs.message.insert and ordinal 1; it does not establish availability in every installed release. These paths do not establish plan support for FIFO deduplication, batch operations or dead-letter movement. Confirm the exact operation, backend and installed version before requesting capture.ModifyTable → Result tree estimates that insert. The relation name identifies a physical table, not necessarily the queue URL or origin name. Plan Rows estimates the output at each node; it does not count delivered messages. Total Cost uses PostgreSQL planner units, not milliseconds. Compare costs only for comparable statements, inputs and database contexts.
A direct values insert need not have an Index Scan or an Index Cond. That absence does not show a missing queue index or describe the later receive path. PostgreSQL receives use a different statement to select eligible rows and claim them with FOR UPDATE SKIP LOCKED; FIFO group selection and dead-letter routing add other work. A send plan does not qualify those statements or prove that a particular message was visible to a consumer. If a separately supported statement’s plan includes an index condition, residual filter or nested scan, inspect those predicates and row estimates together rather than assuming the root node explains all work.
planningContext: "committed-state-observation" means the observer uses the actual compiled SQL and encoded parameters on a separate authenticated, read-only PostgreSQL connection. It runs EXPLAIN (FORMAT JSON) without ANALYZE; it does not insert a second message, measure execution time, or share the original send’s transaction snapshot. The native result and independently observed message or business state establish effects. A complete plan may arrive in a later report revision; unsupported context or unavailable planning capacity must remain an explicit limitation.
Service Bus and Pub/Sub: inspect broker evidence
For an Azure Service Bus queue, investigate the selected broker entity, send acknowledgment and the consumer’s later lock handling. For a Google Cloud Pub/Sub Standard mapping, investigate publish acknowledgment, subscription delivery and acknowledgment behavior. These are actual supported backend profiles, but their availability does not imply every operation has complete Explain capture. Read the report’s recorded admission decisions, planned effects, observed outcomes and declared gaps for the captured operation. Use the native message ID and separately obtained broker or application observations to connect the send with processing. No PostgreSQL plan belongs to these message operations. A broker acknowledgment does not prove that a worker completed the invoice, and it does not turn broker timing or delivery state into a report field when that evidence was not recorded. For the slow-worker case above, supported receive capture can recordsqs.receive.visibility-seconds, sqs.receive.visibility-source and sqs.receive.wait-seconds. These describe selected settings; sqs.receive.message-eligibility can remain unknown. A Service Bus lock that expires or is lost across an adapter restart differs from a durable PostgreSQL receipt handle. A Pub/Sub subscription’s acknowledgment behavior differs again. Compare the installed backend’s rules and actual receive/delete outcomes before deciding to retry.
Full PostgreSQL plans remain private to the exact report owner in every format. They may contain physical relation names and application values inside predicates. Sanitize a copy before sharing it, even when the message body has already been removed from the support bundle. See PostgreSQL plan interpretation and privacy.
For a support handoff, include redacted queue URL and ARN, account and Region, Standard or FIFO profile, target backend, queue attributes, message/group/dedup IDs where relevant, receive and delete times, SDK error and attempt IDs, report revision and limitations, and independent business-state observation. Remove message bodies and credentials from the shared bundle. Use Troubleshooting Explanations for missing receipts or report access failures.
A Support Agent can help correlate the queue backend, claim timeline and reviewed report without treating a duplicate delivery as permission to replay a business action.