> For the complete documentation index, see [llms.txt](https://docs.usegravity.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.usegravity.app/gravity-server/background-jobs.md).

# Background Jobs

Gravity supports background jobs with [Bull.js](https://github.com/OptimalBits/bull). These are used for offloading longer tasks to a separate process. There is a working example included that manages an [automated onboarding flow](/gravity-server/user-onboarding.md).

{% hint style="info" %}
For more information, [please read the Bull docs](https://github.com/OptimalBits/bull).
{% endhint %}

## 1. Add Your Redis URL

You will need to set up a Redis database for tracking the job queue and then add the URL to the following environment variable:

<pre class="language-javascript"><code class="lang-javascript"><strong>REDIS_JOB_URL=
</strong></code></pre>

## 2. Start The Worker

Run the following command to start the background worker:

```
node worker
```

The worker will process jobs added to the queue.

{% hint style="warning" %}
If you're using Mongo, the setup wizard will inject mongo.connect() into the worker. If you bypassed the setup wizard, you need to add this manually.
{% endhint %}

There's also a `Procfile` included to start a separate worker dynos on [Heroku](https://heroku.com) automatically. Other platforms will vary in how you set this up.

The default worker has a `setTimeout` function in `worker/index.js` – you should replace this with your own job function.&#x20;

## 3. Add a Job To The Queue

There are two ways to add a job to the queue in Gravity:

1. Internally
2. Using the API

To add a job on the server, use the following code:

```javascript
const Queue = require('bull');
const jobQueue = new Queue('jobs', process.env.REDIS_JOB_URL);

async function addJob(){

 const job = await jobQueue.add({ /* your custom metadata here */ });
 
}
```

To add a job via the API, make a POST request to:

```javascript
POST /api/job
```

## Updating the Job Progress

It's helpful to set different statuses during the lifecycle of the job:

```javascript
const job = await jobQueue.getJob(id);
job.progress('started');
```

## Updating The Job Data

If you want to update the job metadata, make a PATCH request to:

```javascript
PATCH /api/job/:id
```

The request body will be merged with the existing job data.

## Getting a Job's Status

Once a job has begun, you'll want to check it's status and perform an action when it has completed. To do this, make a GET request to:

```
GET /api/job/:id
```

You can determine if a job has finished using the `finishedOn` key.

You can also fetch a job internally without using the API with:

```javascript
const job = await jobQueue.getJob(id);
```

## Delete a Job

{% hint style="danger" %}
If a job has already started, you can't delete it from the queue.&#x20;
{% endhint %}

You can delete a job that hasn't been executed yet using the the API:

```javascript
DELETE /api/job/:id
```

or anywhere in your internal app:

```javascript
const job = await jobQueue.getJob(req.params.id);
await job.remove();
```
