Welcome to Day 5 of 12 Days of DigitalOcean! Yesterday, you set up your Birthday Reminder Service to run on DigitalOcean Functions, meaning it’s now serverless and cloud-ready. 🎉 Today, you will be taking it a step further by automating it to run on its own schedule—no manual input required.
By the end of this guide, your service (or any other function you’re working on) will run automatically at a set time every day. That means no more remembering to trigger it yourself—it just works.
Deploying your function to the cloud was a big win yesterday, but having to run it manually defeats the purpose of automation. Today’s focus is on scheduling the service to run automatically—like clockwork—so you can set it and forget it. DigitalOcean Functions has built-in scheduling using Triggers for this exact purpose, and you have two ways to set it up.
By the end of today, you’ll know how to:
doctl
CLI and project.yml
.Before getting started, ensure you have the following:
doctl
CLI, you’ll need the project.yml
file for your function. You can check out Day 4 for instructions on installing and setting up the doctl
CLI, and creating the project.yml
file.DigitalOcean gives you two options for setting up triggers:
doctl
CLI for more robust and programmatic control.Warning: Remember that triggers created in the Control Panel are lost if you redeploy the function using the CLI. If you’ll be redeploying often, use Option 2 to add triggers directly to the project.yml
file.
The easiest way to set up a trigger is through the DigitalOcean Control Panel. It’s quick, requires no setup, and is ideal for simple one-off configurations.
reminders/birthdays
) and click the Triggers tab.daily-birthday-trigger
. The name must contain only alphanumeric characters, dashes, and periods.0 9 * * *
means the function will run every day at 9:00 AM.Note: If you not sure how cron works? Check out crontab.guru for a handy guide.
Once you’ve created your trigger, it’s a good idea to test it to ensure everything works as expected. Jump to the Test the Automation section below to learn how.
Warning: While the dashboard is simple and effective, any triggers you create here will be overwritten or deleted if you redeploy the function using the CLI. For frequent updates or programmatic deployments, skip to Option 2.
doctl
CLI with project.yml
You can also create triggers by adding them directly to your project.yml file. This method is more reliable for frequent redeployments because it ensures your triggers are always included in the function’s configuration. Unlike the Control Panel option described earlier, this approach prevents triggers from being overwritten or lost during redeployments.
Here’s how you can set it up:
Open your project.yml
file from Day 4: Deploying Birthday Notifications with DigitalOcean Functions. It might look something like this:
packages:
- name: reminders
shared: false
environment:
DO_DB_NAME: "${DB_NAME}"
DO_DB_USER: "${DB_USER}"
DO_DB_PASSWORD: "${DB_PASSWORD}"
DO_DB_HOST: "${DB_HOST}"
DO_DB_PORT: "${DB_PORT}"
TWILIO_ACCOUNT_SID: "${TWILIO_ACCOUNT_SID}"
TWILIO_AUTH_TOKEN: "${TWILIO_AUTH_TOKEN}"
TWILIO_PHONE_FROM: "${TWILIO_PHONE_FROM}"
TWILIO_PHONE_TO: "${TWILIO_PHONE_TO}"
functions:
- name: birthdays
runtime: python:default
Add a triggers
section to your function configuration to define the schedule:
triggers:
- name: daily-birthday-trigger
sourceType: scheduler
sourceDetails:
cron: "0 9 * * *"
Final updated project.yml
file:
packages:
- name: reminders
shared: false
environment:
DO_DB_NAME: "${DB_NAME}"
DO_DB_USER: "${DB_USER}"
DO_DB_PASSWORD: "${DB_PASSWORD}"
DO_DB_HOST: "${DB_HOST}"
DO_DB_PORT: "${DB_PORT}"
TWILIO_ACCOUNT_SID: "${TWILIO_ACCOUNT_SID}"
TWILIO_AUTH_TOKEN: "${TWILIO_AUTH_TOKEN}"
TWILIO_PHONE_FROM: "${TWILIO_PHONE_FROM}"
TWILIO_PHONE_TO: "${TWILIO_PHONE_TO}"
functions:
- name: birthdays
runtime: python:default
triggers:
- name: daily-birthday-trigger
sourceType: scheduler
sourceDetails:
cron: "0 9 * * *"
This tells DigitalOcean to run the birthdays
function every day at 9:00 AM.
triggers
section: Defines the name, type, and schedule for the trigger. You can name your trigger anything descriptive, like daily-birthday-trigger
.
cron
: Specifies the time the function will run daily in UTC. The cron expression 0 9 * * *
for example, schedules the function to run every day at 9:00 AM.
Save the file and deploy it by running the following command from the directory containing the my-birthday-reminder-service
folder:
doctl serverless deploy my-birthday-reminder-service
Important: Make sure to run the command from the parent directory, not inside the my-birthday-reminder-service
folder. Running it from the wrong location can result in an error like this:
❯ doctl serverless deploy my-birthday-reminder-service
Error: ENOENT: no such file or directory, lstat
Once the deployment is successful, you’ll see a confirmation message similar to this:
Deployed functions
- reminders/birthdays
Deployed triggers:
- daily-birthday-trigger
Go to your dashboard to verify that the trigger has been created under the Functions section.
Pro Tip: To test your trigger, temporarily set the cron expression to a few minutes from now (e.g., 28 9 * * *
if it’s 9:25 AM). After confirming that it works, update it back to your intended schedule and redeploy.
Let’s test your triggers to make sure they’re working. Instead of waiting for them to fire on their usual schedule, you can temporarily set them to run a few minutes from now. Here’s how to do it:
Set the cron expression for your trigger to a few minutes from the current time (in UTC). For example, if it’s 9:25 AM UTC, set the cron expression to 28 9 * * *
so the function runs at 9:28 AM UTC.
Note: Not sure how to convert your local time to UTC? Tools like Time Zone Converter can help.
Save the updated trigger (if using the Control Panel) or redeploy your updated project.yml
file (if using the CLI):
doctl serverless deploy my-birthday-reminder-service
Wait for the trigger to execute, then check the activation logs to confirm the function ran successfully:
doctl serverless activations logs --function reminders/birthdays --last
Note: Activation logs record details about when your function was executed, including whether it ran successfully or encountered errors. They’re a helpful way to verify that your trigger fired at the scheduled time.
This command will return the details of the most recent activation of your function. For example, you might see something like this:
=== 59e8e4f482874d79a8e4f48287dd79ef success 12/23 07:46:33 reminders/birthdays:0.0.6
2024-12-23T07:46:33.323205805Z stdout: Message sent for Charlie Brown. Message SID: SM85f5caeb3ec09239e0d8bdaaba2b158b
This confirms that the trigger fired and the function was activated successfully! 🎉
Note: Once you’ve verified everything is working, update the cron expression to your intended schedule (e.g., 0 9 * * *
for 9:00 AM UTC daily) and save or redeploy.
While the activations logs
command is a great way to check recent executions, sometimes you’ll need more detailed logs to debug or investigate issues with your function. DigitalOcean also provides options to forward these logs to external logging services, making monitoring and troubleshooting your application easier over time.
On Day 6, you will learn to view logs directly, interpret them effectively, and set up log forwarding to external services like Logtail or Papertrail. These tools will help you easily stay on top of your function’s performance.
Here’s what you accomplished today:
doctl
CLI.Here are the previous tutorials from this series:
Up Next: Now that your service runs independently, the next step is monitoring it effectively. In the next tutorial, you will learn how to view your function logs and forward them to external services to simplify tracking and troubleshooting. See you then!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!