How to Enable/Disable a Lambda Trigger on a Schedule

Photo by Mika Baumeister on Unsplash

Why do I try to avoid this?

Let’s start with some reasons why I usually try to avoid enabling and disabling Lambda event source mappings on a schedule.

  • There isn’t a native way to do it, so any solution will add complexity and risk by requiring extra infrastructure and potentially code.
  • Disabling and enabling triggers will likely affect quality attributes such as latency and availability in unintuitive ways.
  • A pause in processing could lead to an insurmountable backlog if not properly accounted for.
  • Scheduled changes to infrastructure and processing behaviour will make the system more difficult to reason about.
  • Any bursts of activity upon re-enabling the trigger could cause more downstream problems than the ones being prevented.
  • Wanting to do something like this is often an indication that something else could be improved instead.

Why would we do this?

Of course, these are just tradeoffs and you may be happy to accept them. Let’s look at some example reasons why one may consider doing so.

Prevent a downstream component from being overloaded

For example, the bulk of your user activity happens around lunch time and any outage would be especially costly then.

Something can only be done during specific times or on specific days

Maybe trades can only be submitted during particular opening hours on weekdays when the market is open.

An activity should only happen during specific times

You only want to send invoices during the night. This is similar to the above, but more of a business rule than a strict requirement.

Batching up work

Perhaps it’s far more efficient and cheap to process items as a large batch than individually, so you let them queue up over time (longer than the 5 minutes aleady supported for sources like SQS).

Third party requirements

It’s them, not you. An external service provider has asked you not to call their API during their weekly scheduled maintenance window.

Your unique reason

Did you find this blog post because you have a reason? What is it? I’d love to know. Please comment!

Is there something else we can do instead?

Some of the above reasons may well be valid, including yours, but let’s take a look at the one I find most questionable: prevent a downstream component from being overloaded. Below are some scenarios and some potential solutions.

Shared resources

Your service shares some resource with another service. This may be the result of how a monolith was broken up into services. For example, perhaps your company has a legacy shared database.

Shared limits

This is especially applicable in cloud environments like AWS. A good example is Lambda concurrency where each account gets 1,000 concurrent invocations by default. This limit is shared between all functions in the account and invocations are throttled when its hit, so functions belonging to different services can intefere with each other.

Synchronous messaging

Services that communicate with another service using synchronous request/response messaging such as HTTP are temporally coupled because the other service must be available for the first to do its work. Moreover, the other service must have capacity for your workload as well as any other. An increase in activity from one service can easily intefere with another.

Asynchronous messaging contention

Maybe there is already a buffer between your service and the other one. Your service does its work and sends messages that are queued up for processing. However, your messages are drowning out another service’s more important messages. This is causing significant latency on processing the other services messages during peak hours. Maybe this is resulting in stale data being served, or orders being processed too slowly.

Short term vs long term

Just because there is something else you could do, doesn’t always mean you should do that right now. If your situation is causing problems and costing you money, you could implement a quick short term fix before working on a longer term solution.

Solution

So, you have a genuinely valid reason, you’re interested in a short-term fix, or you only started reading from here: how can you enable and disable an event source mapping on a schedule?

Enabling and disabling

Lambda’s UpdateEventSourceMapping API action is used to enable/disable. This action takes the UUID of an event source mapping and everything else is optional. We’re only interested in updating the Enabled property.

Scheduling

CloudWatch Events Rules and self-triggering EventBridge Rules can be used for recurring actions like we want. These two are actually the same underlying service, but EventBridge provides more features and is the preferred way to manage events, so we’ll use that.

The missing piece

EventBridge can’t call the UpdateEventSourceMapping action directly, so we need some sort of glue in between. Infrastructure automation is one of Lambda’s selling points and Lambda can be targetted by EventBridge, so it’s an obvious choice. We’ll look at that first, then an interesting alternative.

Lambda

This option involves writing a small function that calls the Lambda API to enable or disable the event source mapping.

Pros and cons

This approach is simple, cheap, and uses Lambda for one of its intended purposes. If you’re used to operating Lambda functions, then you’ll have no trouble here.

API Gateway

As of writing, API Gateway can act as a proxy for 104 other AWS services. These service integrations are very flexible, allowing you to call actions on the other services without writing code, including UpdateEventSourceMapping.

  • HTTP method: PUT,
  • Path: /2015-03-31/event-source-mappings/UUID,
  • Headers: Content-type: application/json, and
  • Body: { "Enabled": boolean }
  • Set the rule target to be API Gateway.
  • Configure the right API, Deployment Stage, and Integration Target.
  • Add a header with key Content-Type and value application/json.
  • Change the constant JSON text. This will now be used for HTTP body and be proxied to UpdateEventSourceMapping, so it must suit the Lambda API:

Security

API Gateway supports three different endpoint types; edge-optimized, regional, and private. There is no point using an edge-optimised endpoint since both EventBridge and Lambda are regional. Since EventBridge doesn’t support private API endpoints, we should use a regional endpoint.

Pros and cons

Using an API Gateway service integration instead of a Lambda means you aren’t deploying any extra code. It’s still serverless, so you aren’t paying anything between invocations. Once you understand service integrations, this solution is just as simple, if not simpler, than the Lambda option.

Example code

In both the Lambda and API Gateway solutions, you may want to do a little more before calling them production worthy. For example, error handling, logging, alarms, tuning the EventBridge retry policy, etc.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store