sorenandersen.com

Using Lambda Destinations for asynchronous invocations

September 08, 2020

In the last write-up we looked at a simple example of using EventBridge as an enabler of decoupled, scalable and maintable event-driven architectures.

When Lambda functions are invoked asynchronously we need a way to track failed invocations. Lambda Destinations is the preferred solution to this, and to generally provide a way of sending asynchronous function results to other services as a mean of simplifying event-driven applications and reducing code complexity.

With Destinations we can route the result of asynchronous invocations - including version, timestamp, request context & payload and response context & payload - to a destination resource without writing additional code. We can set up destinations for both successful and failed invocations to the following supported destinations:

  • Another Lambda function
  • SNS topic
  • SQS queue
  • EventBridge event bus

So I made an example, showing a function that processes asynchronous invocations via EventBridge. When the function returns a successful response, Lambda sends a record of the invocation back to the EventBridge bus for other services to react on. When an invocation fails all processing attempts, Lambda sends an invocation record to a designated SQS queue that effectively acts as our DLQ.

Setting up Destinations is as easy as specifying the ARN of the target resource. The following function will be triggered by matching patterns on the custom event bus. And it’ll emit records of successful invocations to the same bus while failed attempts will be sent to a purpose-made queue.

functions:
  processor:
    handler: functions/processor.handler
    events:
      - eventBridge:
          eventBus: ${self:custom.eventBus.arn}
          pattern:
            source:
              - demo.calculator
            detail-type:
              - multiplication
              - division
    destinations:
      onSuccess: ${self:custom.eventBus.arn}
      onFailure: ${self:custom.failureQueue.arn}

As always we must strive for idempotency in our functions as Lambda does three attempts (configurable with maximumRetryAttempts) before delegating to the failure destination.

I’ve put together a runnable example here. Consult the README for examples on how to ingest both good and bad data with curl and how to inspect the logs/bus/queue for invocation results.

References


Søren Andersen

Digital garden of Søren Andersen.
Posts on tech that I use and learn.