# AsyncEventsDropped: diagnose Lambda async event loss

> AsyncEventsDropped counts Lambda async events discarded after age or retry limits. Check throttling, destinations and DLQs, then verify processing recovery.

By Boris Tane, Founder of Polylane · Published October 6, 2026 · 6 min read
Canonical: https://polylane.com/learn/troubleshooting/AsyncEventsDropped/

AsyncEventsDropped counts Lambda asynchronous events discarded without successful function execution. Events can exceed maximum age, exhaust function-error retries, or be diverted immediately when reserved concurrency is zero. Compare event age, errors and throttles, inspect the exact invocation target's configuration, and verify failure capture.

`AsyncEventsDropped` counts Lambda asynchronous events discarded without successful function execution. The [official metric definition](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics-types.html#async-invocation-metrics) names maximum event age, exhausted retries and reserved concurrency zero as reasons. Compare event age, errors and throttles, then inspect failure capture for the exact function, version or alias the producer invokes.

A retained failure can still count as dropped. The metric describes failed original processing; the destination or DLQ tells you whether a recoverable payload survived.

## Meaning: acceptance is not completion

An asynchronous [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html) uses `InvocationType=Event`. HTTP 202 acknowledges acceptance into Lambda's internal queue, not the handler's successful result. Later execution can fail, retry, wait for capacity or expire.

`AsyncEventsReceived` counts queued events, whereas `Invocations` counts function executions, including retries. Do not subtract them to estimate loss over a short interval. One event can cause several executions, queued work can cross the interval boundary, and Lambda's eventually consistent queue can deliver duplicates even without an error.

Dropped also does not mean never attempted. A handler might complete a side effect and then fail. Check the original business ID in the downstream system before replaying; the metric alone cannot establish whether that side effect happened.

## Causes: age, retries and unavailable capacity

AWS documents separate retry paths in [asynchronous error handling](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-error-handling.html):

- **Function errors**, including timeouts: by default two retries after the initial execution, waiting one minute and then two minutes.
- **Throttling and system errors**: Lambda returns the event to its queue and retries for up to six hours by default. Intervals increase from one second to a maximum of five minutes, and a large queue can further slow retries and reads.

The [configuration API](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionEventInvokeConfig.html) accepts `MaximumEventAgeInSeconds` from 60 to 21,600 and `MaximumRetryAttempts` from zero to two. Retry attempts govern function errors; they do not turn the throttling path into a two-retry policy. A short maximum age can expire an event before capacity or a dependency recovers.

Reserved concurrency zero is a special case. AWS [states](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-retain-records.html) that new async events begin going directly to the configured DLQ or on-failure destination without retries. Restoring concurrency does not automatically replay records already sent there. Check whether zero was intentional and identify the resulting recovery backlog.

Do not invent a most-common cause from the metric name. Use errors, throttles, age and configuration changes to determine which documented path occurred for your function.

## Confirm the metric and related signals

In **CloudWatch → Metrics → All metrics → Lambda**, select the affected function and graph `AsyncEventsDropped` with **Sum** at a one-minute period. Align the same window with these signals from the [metric guide](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics-types.html):

| Metric | Statistic | Diagnostic question |
| --- | --- | --- |
| `AsyncEventsReceived` | Sum | Are producers successfully enqueueing? |
| `AsyncEventAge` | Maximum and useful percentiles | How long did events wait before invocation? |
| `Errors` | Sum | Are handlers failing or timing out? |
| `Throttles` | Sum | Is execution capacity unavailable? |
| `ConcurrentExecutions` | Maximum | Is concurrency reaching a configured limit? |
| `DestinationDeliveryFailures` | Sum | Did invocation-record delivery fail? |
| `DeadLetterErrors` | Sum | Did DLQ delivery fail? |

`AsyncEventAge` is observed when Lambda invokes the function; it is not a complete inventory of every event still waiting in the queue. Rising age is useful evidence of delayed processing but not a payload-level queue inspector.

Use a precise UTC incident range for a terminal query:

```bash
export AWS_REGION=us-east-1
FUNCTION=orders-worker
aws cloudwatch get-metric-statistics --region "$AWS_REGION" \
  --namespace AWS/Lambda --metric-name AsyncEventsDropped \
  --dimensions Name=FunctionName,Value="$FUNCTION" \
  --start-time 2026-10-06T10:00:00Z --end-time 2026-10-06T11:00:00Z \
  --period 60 --statistics Sum
```

Replace the sample times. Sort returned datapoints by timestamp before aligning them with logs. Missing points are not proof of successful processing: confirm producer traffic, account, Region and the resource dimension being queried.

## Inspect the producer's actual target

If the producer uses `orders-worker:live`, inspect the alias and configuration rather than assuming `$LATEST` settings apply:

```bash
aws lambda get-alias --function-name "$FUNCTION" --name live
aws lambda get-function-event-invoke-config \
  --function-name "$FUNCTION" --qualifier live
aws lambda list-function-event-invoke-configs --function-name "$FUNCTION"
aws lambda get-function-concurrency --function-name "$FUNCTION"
aws lambda get-function-configuration --function-name "$FUNCTION" \
  --query '{Timeout:Timeout,DLQ:DeadLetterConfig,Role:Role}'
```

In the console, inspect **Configuration → Asynchronous invocation** and **Configuration → Concurrency**, with the relevant version or alias selected. Save the maximum age, retries, failure destination, DLQ, execution role and any concurrency change during the incident.

A missing explicit configuration does not mean "no retries." Compare default behavior and all configured target settings before deciding which policy governed the call. Match the producer's ARN to what you inspected.

## Fix the cause and retain future failures

For rising `Errors`, read timeout and exception logs and repair the handler or its dependency. For rising `Throttles` and age, inspect reserved and account concurrency and other workloads consuming capacity. Raising concurrency helps only if the downstream service can absorb the resulting load. Initialization failures such as [EC2ThrottledException](/learn/troubleshooting/EC2ThrottledException/) need their own preparation/API investigation.

Increase maximum age only if delayed processing still has business value. A late report may be acceptable; a stale time-limited authorization may not be. Retain idempotency even when the immediate failure is fixed, because retries and duplicates remain part of the invocation model.

Configure failure capture before the next incident. This example targets an existing standard SQS queue; replace its ARN and grant the function execution role `sqs:SendMessage` on it first:

```bash
aws lambda update-function-event-invoke-config \
  --function-name "$FUNCTION" --qualifier live \
  --maximum-event-age-in-seconds 21600 \
  --maximum-retry-attempts 2 \
  --destination-config '{"OnFailure":{"Destination":"arn:aws:sqs:us-east-1:123456789012:orders-async-failures"}}'
```

The [configuration guide](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-configuring.html) recommends `update` for selected changes; `put` overwrites configuration and removes omitted settings. Re-read both failure and any existing success settings after updating. If there is no explicit configuration yet, check the API result and configure the initial policy intentionally rather than treating a missing resource response as success.

AWS [supports](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-retain-records.html) standard SQS, standard SNS, Lambda and EventBridge destinations, plus S3 for failures only. Invocation records include request payload, response context and the failure condition. A Lambda DLQ instead carries the original event with error attributes and supports standard SQS or SNS. Destination settings can be per function, version or alias; DLQ settings are function-level.

Check permissions, encryption policies, resource existence and payload size. Unsupported FIFO destinations fail delivery. SNS's 256 KB maximum can be exceeded by a large async payload plus record metadata. Alarm on delivery-failure metrics separately: a configured target ARN does not guarantee successful retention.

## Verify capture and replay without duplicating effects

Use a test alias or disposable function to exercise a known failure. Confirm that the record reached the destination, inspect its failure condition and original payload, and check delivery-failure metrics. Then send a known successful event through the repaired path and verify its business result.

Replay only retained operations that still need completion. A destination wraps the original input in `requestPayload`; sending the entire record changes the handler's input schema. A DLQ body has a different shape. Extract the intended payload, retain the original idempotency key and rate-limit replay so it does not recreate the backlog.

Without successful capture, the metric cannot reconstruct the event. Check an upstream retained source or audit trail for replay options instead of promising recovery from CloudWatch counts. Restoring capacity is not the same as completing all discarded work.

SQS-triggered Lambda uses polling and synchronous batch invocation. Its recovery policy belongs on the source queue. Follow [ChangeMessageVisibility](/learn/troubleshooting/ChangeMessageVisibility/) for visibility and Lambda mapping settings rather than applying this async-queue policy to SQS messages.

## Prevention

Alert on dropped events where every accepted event matters, and earlier on event age relative to your processing deadline. Group age, errors and throttles into [one incident](/learn/alert-triage/how-to-group-noisy-alerts-into-one-incident/) with the likely cause and impact. Monitor failure-target backlog and age too: captured work that nobody reprocesses is still unfinished.

Polylane's [AWS integration](/integrations/aws/) connects it to AWS, so it can see when a function starts dropping events and work out why. The [AWS overview](/for/aws/) has more. Retention, idempotency and replay still need to be configured in AWS and the application.

Running on AWS? See [how Polylane monitors AWS in production](https://polylane.com/for/aws/).

## Common questions

**Does AsyncEventsDropped mean the function never ran?**

Not necessarily. An event can be discarded after function-error retries were exhausted, so the handler may have run and failed several times. Others expire before execution or are diverted with reserved concurrency zero.

**Does a DLQ keep AsyncEventsDropped at zero?**

No. Capturing a failed event does not make original processing successful. Check the failure target and DeadLetterErrors or DestinationDeliveryFailures as well as dropped-event counts.

**Does MaximumRetryAttempts control throttling retries?**

It controls function-error retries, from zero to two. Throttling and system errors follow the queue retry path and are bounded by maximum event age, rather than the same two-retry limit.

**Does this metric describe SQS-triggered Lambda processing?**

No. SQS event source mappings poll the queue and invoke synchronous batches. Inspect the SQS visibility timeout, redrive policy and mapping instead of Lambda's internal asynchronous queue.

**Can CloudWatch recover the dropped payload?**

No. The metric is a count, not event storage. Recover from a successfully delivered failure destination, a DLQ or an upstream replay source. Without retained payloads the count cannot reconstruct an event.

## Sources

- [Lambda metric definitions](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics-types.html)
- [Asynchronous errors and retries](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-error-handling.html)
- [Retaining asynchronous invocation records](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-retain-records.html)
- [Asynchronous configuration API](https://docs.aws.amazon.com/lambda/latest/api/API_PutFunctionEventInvokeConfig.html)
- [Configuring asynchronous error handling](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-configuring.html)
- [Polylane AWS integration](https://docs.polylane.com/integrations/aws)

## About the author

Boris Tane is the founder of Polylane. He previously founded Baselime, observability for the future of the cloud, which Cloudflare acquired. At Cloudflare he built and led the Workers observability team.

## Related

- [ChangeMessageVisibility: troubleshoot SQS message timeout errors](https://polylane.com/learn/troubleshooting/ChangeMessageVisibility/): ChangeMessageVisibility resets SQS message visibility. Use current receipt handles, bounded timeout extensions and per-entry batch error checks with Lambda.
- [EC2ThrottledException: fix Lambda EC2 API throttling](https://polylane.com/learn/troubleshooting/EC2ThrottledException/): EC2ThrottledException means EC2 throttled Lambda initialization. Check VPC state and API activity, distinguish concurrency limits, and verify a safe recovery.
- [How to group noisy alerts into one incident](https://polylane.com/learn/alert-triage/how-to-group-noisy-alerts-into-one-incident/): Group noisy alerts into one incident: pick grouping labels, set group_by and timers, inhibit downstream symptoms and key incidents on the group key.
- [Fix 502 Bad Gateway on AWS API Gateway and Load Balancers](https://polylane.com/learn/troubleshooting/aws-502-bad-gateway/): Why AWS returns 502 Bad Gateway from API Gateway or an Application Load Balancer, how to find which hop wrote it, and the fix for each cause.
- [Fix 403 Forbidden (Access Denied) from Amazon S3](https://polylane.com/learn/troubleshooting/aws-403-forbidden/): Why Amazon S3 returns 403 Forbidden: Block Public Access, missing s3:ListBucket, object ownership, clock skew, expired presigned URLs and CloudFront. Fix each.

Get started with one command: `curl -fsSL https://polylane.com/setup | bash` installs the CLI, connects your coding agents, and creates the account.
