Writing Jobs - Step by Step
Best practices for writing well-behaving Jobs in your codebase
Pre-requisites
This guide assumes you already have a project setup and working with Trigger.dev. If not, head over to our Quick Start guides to get up and running in a few minutes.
1. Define your Job
A Job is a collection of Tasks that are run in a specific order. You can think of it as a function that you can run on a schedule, or when an event happens. Jobs are defined by calling the TriggerClient.defineJob
function
If you aren’t seeing defined jobs in your Trigger.dev dashboard, it might be because the job file isn’t being imported in your app.
2. Choose a name and ID
Each job must have a unique and stable id
and name
. The id
is used to identify the Job in the database, and the name
is used to identify the Job in the UI.
We will pass the value of the id
property through a slugifier because we use it in URLs in our Dashboard. This means you can use any characters you want, but we recommend using only lowercase letters, numbers and dashes.
3. Set the current version
The version
property is used to track changes to your Job. It’s required to be a semantic version string. You can track changes to your Job by incrementing the version number, and we will display in the Dashboard which version each Job Run was created with.
4. Choose a Trigger
The trigger you choose determines how and when a job will run. See our Triggers guide for more information. The Trigger you choose also defines the type of the run payload
argument (more in this below)
5. Add integrations (optional)
Integrations provide a convienent way to create and run tasks against authenticated APIs inside your Job’s run function. You’ll need to pass them in the integrations
option when defining your Job.
6. Implement the run function
The run
function implements your custom code that will be executed when your Job is run. It’s an async function that takes three arguments:
- The run
payload
- The type of thepayload
argument is determined by the Trigger you choose. - An instance of
IO
, which exposes built-in tasks and allows you to create your own, as well as interact with integrations. - A
context
object, which contains information about the current run, such as the run ID, the Job ID, and the Job version. Context reference
We do not compile and ship your code to run on the Trigger.dev server. It runs exactly where you’ve deployed your code (e.g. Vercel).
The run
function you define is like a normal JavaScript function in all respects except one: it will be called one or more times to complete a single Job Run.
This means that you can’t rely on any state that is not persisted between runs, and you must create tasks to ensure that work is not repeated.
Tasks are so important that we’ve dedicated a whole section to them. See our Tasks guide for more information.
Built in tasks
We provide some built-in tasks that you can use in your run function:
Task | Description | Task code |
---|---|---|
Delay | Wait for a period of time | await io.wait("wait", 60); |
Log | Log a message | await io.logger.log("Hello"); |
Send Event | Send an event (for eventTrigger) | await io.sendEvent("my-event", { name: "my.event", payload: { hello: "world" } }); |
Background fetch | Fetch data from a URL that can take longer that the serverless timeout. | await io.backgroundFetch("fetch-some-data", { url: "https://example.com" }); |
For a full list of built-in Tasks, see the io SDK reference. The below example makes use a few of these built-in tasks:
Create your own tasks
You can also create your own tasks or use tasks provided by our integration packages. See Creating Tasks for more information. The example below demonstrates creating tasks in 3 different ways:
7. Handling errors
If your run function throws an error, the Job Run will fail and the error will be displayed in the Dashboard. If you’d like to retry on an error, you can do so using tasks and the retry
option.
See the retry options for more information.
8. Skip catching internal errors
We will throw some errors internally to interrupt run execution so they can be resumed later. If you put a try/catch
block in your run code and catch these errors, your job will not work correctly. You can check if an error is an internal error using isTriggerError():
Alternatively, you can use the io.try() function:
9. Creating tasks in a loop
If you want to create tasks in a loop, you should use for const ... of
to ensure that the tasks are created in the correct order.
We don’t currently support running tasks in parallel so Promise.all
will not work correctly.
This is something on our roadmap that we hope to support soon.
10. Return data from your Job
Anything you return from the run
function will be automatically set as the run output and displayed in the Dashboard.
Next steps
We recommend exploring all of the below sections to fully understand how to create and run Jobs using Trigger.dev.
Running your jobs
A guide for how to run your Jobs. Triggering a test Run and Triggering your Job for real
Integrations
Integrations make it easy to authenticate and use APIs. Learn how to use and create integrations.
API catalog with code samples
Find code examples for many popular APIs. These can be copied / modified for use in your own projects.
SDK reference
How to use the SDK. This includes all the available Tasks, triggers and actions you can use.
Was this page helpful?