Blazalek.com

Queues, Webhooks and Sending Reliability

On this page

Why are webhook events delivered more than once, and how should processing be made idempotent?

Severity: HighPause sending: Pause conditionally

Assume webhook delivery can be at least once and that lost acknowledgements can create duplicates. Deduplicate before side effects using the provider's stable event ID, such as sg_event_id or svix-id. Pause non-idempotent downstream effects until repeated IDs are safely ignored.

First 15 minutes

  1. Compare duplicate SendGrid payloads by sg_event_id when that field is included.
  2. Check for non-2xx Event Webhook responses that trigger SendGrid retries for up to 24 hours.
  3. Compare Resend duplicates by svix-id and confirm already processed IDs are skipped.

Now

  • Store and skip repeated sg_event_id or svix-id values before executing downstream side effects.

Next 24 hours

  • Make event-ID persistence and the downstream side effect one idempotent processing path.

Next 7 days

  • Use the provider event timestamp when application state depends on event order, because Resend does not guarantee delivery order.

Technical checks

Engineering

  • Persist and deduplicate SendGrid sg_event_id values when included.
  • Confirm the SendGrid endpoint returns a 2xx response for successful processing so non-2xx retry behavior is not triggered.
  • Use the Resend created_at timestamp rather than arrival order when event order must be reconstructed.

Verification criteria

  • Replay payloads with the same sg_event_id and confirm the downstream effect occurs once.
  • Confirm successful SendGrid processing returns 2xx and no non-2xx retry sequence continues.
  • Replay a stored Resend svix-id and confirm it is skipped as already processed.

Escalation criteria

  • Escalate internally when a repeated sg_event_id is not skipped and executes a downstream side effect after local deduplication is enabled.
  • After confirming a stored svix-id is skipped and the downstream side effect occurs once, treat further delivery of that ID as documented at-least-once behavior rather than an escalation condition.

Prevention

  • Treat SendGrid sg_event_id as the deduplication key when included.
  • Store Resend svix-id values and skip IDs already processed.
  • Use created_at rather than arrival order where Resend event ordering matters.

Business impact

  • At-least-once delivery can repeat downstream effects when a lost acknowledgement causes the provider to deliver the same event again.

Provider notes

  • SendGrid retries Event Webhook POSTs after non-2xx responses at increasing intervals for up to 24 hours.
  • Resend provides at-least-once delivery and does not guarantee delivery order.

Open questions

  • Event-ID field names, retry schedules, replay tools and ordering guarantees vary by ESP and webhook product.
  • Whether current duplicates share the same provider event ID or represent distinct upstream events requires payload and persistence inspection.
  • The current handler's acknowledgement timing and atomicity relative to side effects are unknown until code and database transactions are reviewed.
Sources (4)
  1. Twilio SendGrid Event Webhook OverviewDuplicate eventsTwilio SendGrid
  2. Twilio SendGrid Event Webhook OverviewGeneral troubleshootingTwilio SendGrid
  3. Managing WebhooksFAQ: What are the delivery guarantees?Resend
  4. Managing WebhooksFAQ: Do events arrive in order?Resend

Related runbooks

Why is email stuck in the sending queue, and how should we clear the backlog?

Severity: HighPause sending: Pause conditionally

Do not clear the backlog blindly; first determine whether ready messages, oldest-message age, or in-flight work is growing. Classify downstream quota and SMTP outcomes before replay so temporary jobs can be controlled and permanent failures are not repeated unchanged. The business risk comes from increasing queue delay and invalid sends during an uncontrolled drain.

First 15 minutes

  1. Record the ready backlog and the oldest unprocessed message age, using SQS ApproximateNumberOfMessagesVisible and ApproximateAgeOfOldestMessage or equivalent metrics.
  2. Compare in-flight work, consumer errors, and throughput before adding workers or starting a drain.

Now

  • Stop blind replay, isolate stored 5yz jobs for intervention, and keep only classified transient jobs eligible for controlled retry.

Next 24 hours

  • When SES returned the documented quota or maximum-rate error, wait up to ten minutes before retrying API sends and restart at a controlled rate.

Next 7 days

  • Tune consumer capacity from ready, in-flight, error, and throughput evidence instead of backlog count alone.

Technical checks

Engineering

  • Graph ready, oldest-age, and in-flight metrics together and correlate them with worker errors and completed throughput.
  • Verify idempotency at the logical-send boundary before draining an Amazon SQS standard queue that can deliver a message more than once.
  • Classify each stored provider or SMTP result and exclude unchanged 5yz jobs from replay.

ESP support

  • Confirm whether Amazon SES returned the documented daily-quota or maximum-send-rate throttling error before applying its retry guidance.

Verification criteria

  • Ready backlog and oldest-message age both trend down from the incident baseline while completed throughput continues.
  • In-flight work no longer indicates stuck consumers when compared with worker errors and throughput.

Escalation criteria

  • Escalate to engineering when oldest-message age keeps growing despite healthy throughput, and to SES support when the documented throttling condition persists after provider-directed retry handling.

Prevention

  • Alert on ready backlog, oldest-message age, and in-flight work together, require idempotent logical sends, and preserve response classification for every queued job.

Business impact

  • A growing visible backlog or oldest-message age means customer-facing email is waiting longer even when the queue count appears stable.

Provider notes

  • Amazon SQS backlog and age metrics are approximate and should be interpreted with lifecycle, in-flight, error, and throughput evidence.
  • Amazon SES recommends waiting up to ten minutes before retrying API sends only for its documented daily-quota or maximum-rate throttling errors.

Open questions

  • The queue technology, queue depth, oldest-message age, in-flight count, retry schedule, and worker health were not provided.
  • The root cause is unresolved until downstream responses, quota events, worker errors, and backlog age are correlated.
  • Whether consumers are idempotent and whether draining the backlog could duplicate customer-visible email is not available.
Sources (6)
  1. Available CloudWatch metrics for Amazon SQSApproximateNumberOfMessagesVisibleAmazon SQS
  2. Available CloudWatch metrics for Amazon SQSApproximateAgeOfOldestMessageAmazon SQS
  3. Available CloudWatch metrics for Amazon SQSApproximateNumberOfMessagesNotVisibleAmazon SQS
  4. Amazon SQS at-least-once deliveryAt-least-once deliveryAmazon SQS
  5. Errors related to the sending quotas for your Amazon SES accountReaching sending limits with the Amazon SES APIAmazon SES
  6. RFC 5321: Simple Mail Transfer ProtocolSection 4.2.1, Reply Code Severities and TheoryIETF RFC 5321

Related runbooks

Why is SendGrid Inbound Parse not delivering data to our endpoint?

Severity: HighPause sending: Pause conditionally

Treat this first as an end-to-end routing and endpoint-acceptance incident, not as proof that SendGrid lost the message. Verify the dedicated hostname's MX record, public destination URL, request handling, and response code in that order. A valid 2xx stops retry, while documented 5xx retries can end with an undelivered post being dropped after three days.

First 15 minutes

  1. Resolve public MX for the exact dedicated receiving hostname and confirm priority 10 points to mx.sendgrid.net.
  2. Test the configured destination URL from the public internet and capture the final HTTP status without relying on redirects.

Now

  • Correct the dedicated MX target or restore public reachability, and remove any redirect from the configured destination path.

Next 24 hours

  • Fix multipart handling and, when enabled, verify Twilio signature and timestamp headers against the raw request body before parsing.

Next 7 days

  • Make durable acceptance precede the 2xx response and alert on 5xx retries early enough to act before the documented three-day drop point.

Technical checks

IT / DNS

  • Verify the dedicated parse hostname, not the production root domain, has the required priority-10 MX target mx.sendgrid.net.

Engineering

  • Test public DNS, TLS, routing, firewall, and authorization for the configured destination URL.
  • Confirm the endpoint accepts multipart/form-data and file parts within parser and body-size limits.
  • When signature verification is enabled, verify signature and timestamp headers against the raw body before multipart parsing changes it.
  • Review endpoint status logs for redirects, 2xx acceptance, and 5xx retries; a redirect is not followed by the webhook.

Verification criteria

  • Public DNS shows the dedicated hostname's priority-10 MX target as mx.sendgrid.net, and the configured URL is reachable from outside the private network.
  • A controlled multipart event passes any configured raw-body signature check, is durably accepted, and receives a direct valid 2xx response.

Escalation criteria

  • Escalate to Twilio SendGrid when 5xx retries persist and undelivered posts are approaching the documented three-day drop window.

Prevention

  • Continuously test dedicated MX routing, public endpoint reachability, multipart parsing, raw-body signature verification when enabled, and durable acceptance before 2xx.

Business impact

  • Inbound events that remain undelivered after documented 5xx retries can be dropped after three days without advance notification, leaving dependent business processing incomplete.

Provider notes

  • SendGrid does not follow HTTP redirects, and a valid 2xx removes the item from its retry queue.
  • The accepted evidence supports retries for 5xx responses and a three-day drop point; behavior outside that documented server-error scope remains unresolved.

Open questions

  • The receiving hostname, public MX answer, Inbound Parse configuration, destination URL, and endpoint request logs were not provided.
  • The current failure point is unresolved until DNS delivery, HTTP status, redirect behavior, multipart parsing, and signature verification are tested end to end.
  • Twilio's Help Center says any non-2xx response or DNS failure is retried for 72 hours, while the developer page describes 5xx retries specifically; confirm current 3xx and 4xx behavior with Twilio before relying on it.
Sources (6)
  1. Configure the inbound parse webhookCreate an MX recordTwilio SendGrid
  2. Configure the inbound parse webhookSet the email server and webhook URLTwilio SendGrid
  3. Configure the inbound parse webhookExamples of the payloads and their parameters > Default webhook payloadTwilio SendGrid
  4. Inbound Email Parse WebhookRetry behavior and Setup warningsTwilio SendGrid
  5. Securing your Inbound Parse WebhooksValidate Inbound Parse Webhooks > Signature VerificationTwilio SendGrid
  6. Inbound Email Parse WebhookRetry behaviorTwilio SendGrid

Related runbooks

Why are Salesforce Marketing Cloud triggered sends heavily delayed?

Severity: HighPause sending: Pause conditionally

Check the Triggered Send definition and queue before treating the delay as a general Salesforce outage. A Paused or Inactive covered send queues messages until restart, while an asynchronous API success confirms structure rather than final processing. Queued subscribers can expire after three days, so delay can become message loss when the definition restarts.

First 15 minutes

  1. Confirm that the affected Triggered Send definition is in Running or Active status.
  2. If it is Running with a non-empty queue, read the Alert Manager reason and identify the error before restarting the definition.
  3. Treat each initial asynchronous success as structural validation only, not proof of final processing.

Now

  • For an inactive definition, start or restart it and observe the eligible queued messages.
  • For a Running definition in error, resolve the Alert Manager cause before applying the Stop, Publish, Start sequence.

Next 24 hours

  • Reconcile callback results, retained request and response data, RecipientSendId records, and the NotSent extract for the affected period.

Next 7 days

  • Make final callback handling and retention of complete request, response, and RecipientSendId evidence part of the Triggered Send integration.

Technical checks

Marketing / CRM

  • Check the definition status, queue state, and any Alert Manager reason for the affected send.

Engineering

  • Reconcile asynchronous callback results with retained API requests, responses, and RecipientSendId values.
  • Use the NotSent Data Extract to identify excluded subscribers for the affected send.

Verification criteria

  • The definition remains Running or Active while controlled asynchronous tests reach a final callback result.
  • Final callbacks account for initial asynchronous successes without unexplained later failures.
  • RecipientSendId and NotSent checks account for the affected subscribers.

Escalation criteria

  • Escalate when a Running definition still has a queue after the Alert Manager cause is resolved and the documented restart sequence is completed.
  • Provide Salesforce support with callback results, complete requests and responses, RecipientSendId values, and NotSent evidence when those records do not explain the delay.

Prevention

  • Treat the final asynchronous callback as the processing result instead of relying on the initial successful response.
  • Retain RecipientSendId values and review NotSent data so excluded subscribers remain diagnosable.

Business impact

  • Paused or Inactive definitions can leave intended triggered messages queued instead of sent.
  • Subscribers queued longer than 72 hours can move to error when the definition restarts.
  • An asynchronous request can appear initially successful even when later processing fails.

Provider notes

  • Salesforce applies a three-day expiration policy to subscribers queued for the covered Triggered Send types.

Open questions

  • The exact incident cause requires the tenant's triggered-send status, queue state, callback results, NotSent records, and request/response logs.
Sources (6)
  1. Engagement - Marketing Cloud Engagement Triggered Send email (including Journey Builder sends) not sent to subscriberTriggered Send StatusSalesforce Marketing Cloud Engagement
  2. Engagement - Marketing Cloud Engagement Triggered Send email (including Journey Builder sends) not sent to subscriberTriggered Send StatusSalesforce Marketing Cloud Engagement
  3. Engagement - Marketing Cloud Engagement Triggered Send email (including Journey Builder sends) not sent to subscriberTriggered Send Status, running status with queued emailsSalesforce Marketing Cloud Engagement
  4. Engagement - Marketing Cloud Engagement Triggered Send email (including Journey Builder sends) not sent to subscriberTriggered Send Status warningSalesforce Marketing Cloud Engagement
  5. Engagement - Marketing Cloud Engagement Triggered Send email (including Journey Builder sends) not sent to subscriberAPI Call Troubleshooting, Asynchronous API CallsSalesforce Marketing Cloud Engagement
  6. Engagement - Marketing Cloud Engagement Triggered Send email (including Journey Builder sends) not sent to subscriberAPI Call TroubleshootingSalesforce Marketing Cloud Engagement

Related runbooks

How does SendGrid retry a failed Inbound Parse webhook delivery?

Severity: High

SendGrid retries Inbound Parse POSTs that return 5xx responses; a valid 2xx acknowledges the delivery and stops retries. If the message is still undelivered after three days, SendGrid drops it without prior notification. Inspect your endpoint logs promptly because SendGrid provides no dashboard alert and the original sender receives no bounce for a failed POST.

First 15 minutes

  1. Inspect the endpoint's own logs for 5xx responses and repeated delivery symptoms because SendGrid does not provide a dashboard failure alert.
  2. Restore the endpoint so it returns a valid 2xx when it accepts the delivery, before the documented three-day drop point.

Now

  • Restore the endpoint and return a valid 2xx only when it accepts the Inbound Parse delivery.

Next 24 hours

  • Monitor 5xx responses and retry symptoms in endpoint logs while service remains restored.

Next 7 days

  • Exercise endpoint recovery so the team can restore valid 2xx acceptance before the documented three-day drop point.

Technical checks

Engineering

  • Confirm that SendGrid is posting parsed data to the configured Inbound Parse URL.
  • Separate valid 2xx acknowledgements from 5xx responses; do not infer retry behavior for 3xx, 4xx, or DNS failures from the documented 5xx rule.

Verification criteria

  • A controlled Inbound Parse POST receives a valid 2xx and is removed from SendGrid's retry queue.
  • Endpoint monitoring shows accepted deliveries and no recurring 5xx retry symptoms after restoration.
  • Local monitoring detects failed POSTs without relying on a SendGrid dashboard alert.

Escalation criteria

  • Escalate to SendGrid when the endpoint is accepting valid 2xx responses but deliveries still retry or approach the documented three-day drop point, and include endpoint logs because no dashboard alert exists.

Prevention

  • Continuously monitor endpoint 5xx responses and restore valid 2xx acceptance before the three-day drop point.

Business impact

  • Inbound messages that remain undelivered after three days are dropped without prior notification.
  • The original sender receives no bounce and operators receive no SendGrid dashboard alert for failed POSTs, creating a monitoring blind spot.

Provider notes

  • The published automatic-retry behavior is specific to 5xx responses and does not establish a universal rule for 3xx, 4xx, or DNS failures.

Open questions

  • Twilio does not publish the exact increasing retry interval schedule within the documented 72-hour retry window.
Sources (5)
  1. Understanding Inbound Parse Webhook Retry LogicAnswer, initial delivery attemptTwilio SendGrid
  2. Understanding Inbound Parse Webhook Retry LogicAnswer, HTTP status behaviorTwilio SendGrid
  3. Inbound Email Parse WebhookIntroductory retry paragraph and Info callout before SetupTwilio SendGrid
  4. Understanding Inbound Parse Webhook Retry LogicImportant Note on NotificationsTwilio SendGrid
  5. Inbound Email Parse WebhookIntroductory retry paragraph and Info callout before SetupTwilio SendGrid

Related runbooks

Is a Postmark service incident delaying outbound email?

Severity: HighPause sending: Pause conditionally

Do not assume a Postmark-wide incident from delayed mail alone: recheck the live status and inspect affected messages in Activity. Queued means Postmark accepted but has not sent the message and can indicate provider trouble or an account or Message Stream pause. Processed or Delayed messages can instead reflect recipient-server behavior, so isolate the pattern before changing sending.

First 15 minutes

  1. Requery the official Postmark live status because the operational observation from 2026-07-17 can change.
  2. Classify representative affected messages as Queued, Processed, or Delayed in Postmark Activity.

Now

  • Confirm and correct any account or Message Stream pause before submitting more mail to that stream.

Next 24 hours

  • Separate recipient-server Processed or Delayed cases from Postmark Queued cases so each is handled by the responsible party.

Next 7 days

  • Document the Activity decision path for Queued versus Processed or Delayed messages.

Technical checks

Engineering

  • Query the official current status and present unplanned-incident notices.

Deliverability

  • Inspect Activity for Queued, Processed, and Delayed patterns by Message Stream and recipient domain.
  • For Delayed messages, distinguish the documented most-domain retry pattern from domains with different rates or durations.

Verification criteria

  • The current live status and present unplanned-incident notices are consistent with any affected messages that remain Queued in Activity.
  • Affected messages no longer remain Queued after any account, Message Stream, or provider condition is resolved.

Escalation criteria

  • If current status and Activity do not explain the delay, contact Postmark support with a link to an affected Activity message after checking local submission logs.

Prevention

  • Monitor the official current status and present unplanned-incident notices.
  • Retain Activity links and local submission evidence so unexplained cases can be escalated with a specific affected message.

Business impact

  • Queued messages have been accepted by Postmark but remain unsent, which delays the intended communication.
  • Processed or Delayed messages can be held or temporarily refused by the recipient server rather than by a Postmark-wide incident.

Provider notes

  • For Delayed messages, Postmark retries most domains every 10 minutes for up to 12 hours, but some domains use different rates and durations.

Open questions

  • The user-specific cause and whether a delay remains current after verification are unknown without Postmark Activity links, submission logs, and current status evidence.
Sources (6)
  1. Postmark Status API - current status responseLive JSON page.state and page.state_textPostmark
  2. Postmark Status APISimple Overview and List NoticesPostmark
  3. Why didn’t this recipient receive my messageInterpreting the message events, QueuedPostmark
  4. Why didn’t this recipient receive my messageInterpreting the message events, Processed and DelayedPostmark
  5. Why didn’t this recipient receive my messageInterpreting the message events, DelayedPostmark
  6. Why didn’t this recipient receive my messageFinal escalation paragraphPostmark

Related runbooks

Wojtek BlazalekWojtek BlazalekEmail deliverability expert

Stuck in an email incident? I help teams get delivery, reputation and auth back on track.

Hands-on deliverability work for teams that send at scale

Book a free diagnostic callSee services
Need help? Contact us!