Trigger precisely at hh:mm:00 with EventBridge and Lambda
Tags: aws, python
Published: 2022-11-26 03:40:40

## Motivation

In Amazon EventBridge Rules and EventBridge Scheduler, the precision of time is one minute. This is the same as the usual cron jobs. 

> ... the minimum precision for a schedule is one minute. Your scheduled rule runs within that minute, but not on the precise 0th second. ([aws-doc](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html))

Sometimes we want to trigger precisely at zero seconds, for example, at `00:00:00`.

In this post, I share the way to trigger precisely using the Lambda function with the EventBridge Schedule.


## Architecture


![EventBridge invoke Lambda function. After wait, the function trigger anything.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dz2rxtwegpkbgrlvhq6p.png)


1. 
EventBridge invokes the Lambda function **1 minute before** the desired trigger time `00:00:00`. That means the EventBridge Schedule is set to invoke the Lambda function at `23:59`. As written above, we don't know what seconds in 23:59 the time Lambda function will be invoked. (It might be 23:59:16 or 23:59:38...) 

2. The Lambda function calculates the time left to `00:00:00` and sleeps until then.

3. At `00:00:00`, the Lambda function triggers some actions, events or resources.


## Lambda function

Here is the example code for the Python Lambda function. You can just create a new function and paste this. 

Note that the timeout of the Lambda function should be more than 1 minute.

```py
import time
from datetime import datetime, timedelta


def lambda_handler(event, context):

    time_called = datetime.now()
    print("time_called", time_called)

    # ceiling minute
    target = time_called - timedelta(
        minutes=-1,
        seconds=time_called.second,
        microseconds=time_called.microsecond
    )

    diff = target - time_called
    wait_sec = diff.seconds + diff.microseconds / 1000000
    time.sleep(wait_sec)

    time_zero_sec = datetime.now()
    print("time_zero_sec", time_zero_sec)
    
    # Write here what you want to trigger at xx:xx:00.

```

Two `print()` are used to compare the times before and after wait.

### Result

Let's try and see the result. At this time, **desired time is 23:00**. EventBridge Scheduler was set to invoke the Lambda function **at 22:59**.

![EventBridge Scheduler](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jfhkxixgacacyngvfdsu.png)

Here is the capture of CloudWatch logs of the Lambda function.

![CloudWatch logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ek3ziyxw9swjn0tj6gkh.png)

- `22:59:16.345072` is from first print(), when EventBridge triggered the Lambda function.
- `2022-11-25 23:00:00.044251` is from second print(), when the Lambda function waited until `23:00:00` as intended.

Good! This is what I wanted to do here.

## Summary

I've shared how to trigger events precisely in second order using EventBridge and Lambda.

## More to read

[Dennis Traub wrote an interesting post on the same topic **using StepFunctions**. ](https://dev.to/dennistraub/how-to-invoke-an-aws-lambda-function-at-almost-exactly-the-top-of-a-minute-using-aws-step-functions-1g8b)

## Note

There is a parameter `at expression at(yyyy-mm-ddThh:mm:ss)` in EventBridge Scheduler cli/boto3, but `ss` part does not work.