Invoke AWS Lambda function only once, at a single specified future time

16,885

Solution 1

You can schedule lambda event using following syntax:

cron(Minutes Hours Day-of-month Month Day-of-week Year)

Note: All fields are required and time zone is UTC only

Please refer this AWS Documentation for Details.

Thanks

Solution 2

You can use DynamoDB TTL feature to implement this easily, simply do the following:

1- Put item with TTL, the exact time you want to execute or invoke a lambda function.

2- Configure DynamoDB Streams to trigger a lambda function on item's remove event.

Once the item/record is about to expire, your lambda will be invoked. you don't have to delete or cleanup anything as the item in dynamodb is already gone.

NOTE: However the approach is easy to implement and scales very well, but there's one precaution to mention; using DynamoDB TTL as a scheduling mechanism cannot guarantee exact time precision as there might be a delay. The scheduled tasks are executed couple of minutes behind.

Solution 3

You can schedule a step function which can wait until a specific point in time before invoking the lambda with an arbitrary payload.

https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-wait-state.html

Something like this

const stepFunctions = new AWS.StepFunctions()
const payload = {
    stateMachineArn: process.env.SCHEDULED_LAMBDA_SF_ARN,
    name: `${base64.encode(email)}-${base64.encode(timestamp)}`, // Dedupe key
    input: JSON.stringify({
      timestamp,
      lambdaName: 'myLambdaName',
      lambdaPayload: {
        email,
        initiatedBy
      },
    }),
  }
await stepFunctions.startExecution(payload).promise()

Solution 4

I understand its quite late to answer this question. But anyone who wants to use CRON expression to trigger an event(or call an API) only once can use following example:

This event will be triggered only once on January 1, 2025 - 12:00:00 GMT

00 12 01 01 ? 2025

For those who do not have much knowledge of cron syntax:

Minutes Hours DayOfMonth Month DayOfWeek Year

I am using this with AWS Cloudwatch Events and the result looks like this: enter image description here

Note: I did not have to specify Day of week, since I have given it a fixed date and thats obvious.

Share:
16,885

Related videos on Youtube

Ethan Harlig
Author by

Ethan Harlig

Updated on June 18, 2022

Comments

  • Ethan Harlig
    Ethan Harlig almost 2 years

    I want to be able to set a time to invoke an AWS Lambda function, then have that function be invoked then and only then. For example, I want my Lambda function to run at 9:00pm on December 19th, 2017. I don't want it to repeat, I don't want it to invoke now, just at 9:00pm on the 19th.

    I understand that CloudWatch provides Scheduled Events, and I was thinking that when a time to schedule this reminder for is inputted, a CloudWatch Scheduled Events is created to fire in that amount of time from now (so like if you schedule it at 8:22pm to run at 9pm, it’ll be 38 mins), then it invokes the Lambda function at 9pm which then deletes the CloudWatch Scheduled Event. My issue with this is that when a CloudWatch Scheduled Event is created, it executes right then, then at the specified interval.

    Any other ideas would be appreciated, as I can't think of another solution. Thanks in advance!

  • Ethan Harlig
    Ethan Harlig over 6 years
    Maybe I am misunderstanding the documentation, but it seems like all of the examples given for cron expressions are repetitive events. Per their examples, it doesn't seem like I want to use that to invoke a Lambda function once at a given time.
  • RredCat
    RredCat over 6 years
    @EthanHarlig You misunderstand documentation. It is possible to setup cron for repetitive and one time events both. You have to specify year, month, day of month, hour and minutes for your task.
  • Ethan Harlig
    Ethan Harlig over 6 years
    @RredCat I see! So if I wanted to invoke a Lambda at 12:00pm on December 20th (UTC), I would use cron(0 12 20 12 * 2017) and that would specify that it is 12:00, on December 20, 2017, and it doesn't matter what day of week that is?
  • Kush Vyas
    Kush Vyas over 6 years
    @EthanHarlig I agree with RredCat , you can set it up one time and on repeat also.
  • AC88
    AC88 about 6 years
    ~~This doesn't seem to work for me? Trying to set UTC 03:20 (about 4 minutes from now): aws events put-rule --name testing-trigger --schedule-expression 'cron(0 20 3 26 2 ? 2018)' -> An error occurred (ValidationException) when calling the PutRule operation: Parameter ScheduleExpression is not valid.~~ Oops, never mind, starts with minutes, not seconds.
  • madhead
    madhead over 5 years
    Note that CloudWatch does not guarantee exactly once firing. This guy sent emails twice and I'm seeing duplicated data in my croned reports. Because "In rare cases, the same rule can be triggered more than once for a single event or scheduled time, or the same target can be invoked more than once for a given triggered rule". But I want to admit that I see at least one doubled shot every 2 days of 3 for 7 scheduled tasks.
  • Blundell
    Blundell about 5 years
    @madhead you could have your lambda write to a DB field when it it triggered, so if it is triggered twice the second one knows not to execute
  • Gergely M
    Gergely M almost 5 years
    Spot on, thanks! Let me emphasize one thing that caused this error to me (see the notes at the end of the page linked above ): "One of the day-of-month or day-of-week values must be a question mark (?)."
  • Samantha Atkins
    Samantha Atkins over 4 years
    It seems fundamentally wrong to involve dynamodb and all these considerations for something by its nature so simple.
  • RNA
    RNA about 4 years
    you are genius!
  • Gordon Leigh
    Gordon Leigh about 4 years
    So long as you're ok with it actually taking up to 48 hours. According to the docs: "DynamoDB typically deletes expired items within 48 hours of expiration. The exact duration within which an item truly gets deleted after expiration is specific to the nature of the workload and the size of the table. Items that have expired and have not been deleted still appear in reads, queries, and scans. These items can still be updated, and successful updates to change or remove the expiration attribute are honored."
  • U.Rush
    U.Rush about 4 years
  • Thayne
    Thayne about 4 years
    The documentation isn't clear, if a schedule can never trigger again, is it automatically cleaned up?
  • M Faisal Hameed
    M Faisal Hameed over 3 years
    Excellent, thanks for the idea. This is exactly what I was looking for.
  • freethebees
    freethebees about 3 years
    This is a really intriguing method. I really like that this would give the ability to pass arguments to the Lambda function too, unlike a cron execution. It's worth considering, however, deleting an item manually will also trigger the event. So you'll want to check the ExpirationTime in your Lambda.
  • Lukas Liesis
    Lukas Liesis about 3 years
    keep in mind that you can create only 100 rules per account. There is option to ask support to increase this limit, but seems like this is not designed to be used for high scale. Anyone knows someone who uses like 100k such rules on single account?