Developers · Data
Background Jobs
Last updated 1 November 2026
In this article, we describe how you can improve your application performance by utilizing the background Liquid tag.
Why Background Jobs
In Insites, the background tag allows you to push some operations to the asynchronous queue that the system will run independently of the currently served HTTP request. This means it will not block the server's response to the user. Background jobs should be used as performance improvement every time the work is time-consuming (subjectively, we usually try to push any work over 1 second to a background job).
Synchronous vs. Asynchronous
To explain the synchronous and asynchronous concepts of code, we use the example of different types of class lecture setups because we think it illustrates this concept in an easier-to-understand way.
Synchronous
A real-world example of a synchronous event is when classes occur on set schedules and time frames. Students and instructors are online simultaneously in synchronous classes since lectures, discussions, and presentations take place at specific hours. All students must be online at that exact time to participate in the class.
In terms of code, the system executes operations one by one. Every task needs to finish before the system runs the next one.
const log = msg => console.log(msg);
log('Hello');
log('World');This code will log messages in the same order as they appear on the screen:
Hello
WorldAsynchronous
On the other hand, asynchronous classes let students complete their work on their own time. Students are given a one–week timeframe during which they need to connect to their class at least once or twice; you can hit the books no matter what hour of the day (or night) in asynchronous courses.
In terms of code, the system pushes operations to a different context and proceeds with other executions without waiting for them to finish.
const log = msg => console.log(msg);
log('Start');
setTimeout(() => { log('Hello'); }, 5000);
setTimeout(() => { log('World'); }, 1000);
log('Finish');This piece of code will log:
- Immediately - Immediately - Delayed by one second - Delayed by five seconds
Tasks in
Asynchronous code usually helps to maximize CPU cycles' efficiency, minimizing the main thread's block time and wait time for situations where those operations can be potentially long-running.
Source: The synchronous and asynchronous processes was lifted from https://www.elearners.com.
Priorities
You can choose a priority for your job based on its time sensitivity and the estimated time of computation needed. They all have different timeouts after the job is killed, regardless of whether it has finished or not.
| Priority | Timeout |
|---|---|
| high | 1 minute |
| default | 5 minutes |
| low | 4 hours |
- If you need something to happen as soon as possible, choose the
priority. - If you need more than one minute of computation time, or there is a risk of exceeding 1 minute, choose the
priority. - If it's not a time-sensitive job or it is a long-running job, choose the
priority.
Execution Scope
{% background priority: 'low', delay: 5, max_attempts: 3, source_name: 'my custom job', data: my_data, hey: 'hello' %}
{% endbackground %}The background tag creates an entirely new execution context, so you will only have access to variables explicitly provided to the background tag: 'data' and 'hey'. Note that you will not have access to the 'my_data' variable. Also, note that the result of this background tag will not be rendered, and you will not have access to any variable inside the background tag.
Example 1 - High Priority Job
Download a JSON file and put its value into the record field. In this example, we will download the JSON file with currency rates for USD and put the resulting JSON into a database to use further down the road.
{% assign currency = context.params.currency %}
{% background priority: 'high', source_name: 'update-currency-rates', currency: currency %}
{% capture url %}https://example.com/currency-rates.json?currency={{ currency }}{% endcapture %}
{% assign data = url | download_file | parse_json %}
{% graphql g, currency: 'USD', rates: data, field: 'rates' %}
mutation update_currency($currency: String!, $rates: String!, $field: String!) {
record_update(
id: 1337
record: {
table: $currency
properties: [{ name: $field, value: $rates }]
}
) {
id
}
}
{% endgraphql %}
{% endbackground %}This whole operation, because it was pushed out to the background job, will not block the rendering of the page; hence standard request timeout is not applied to it. It can run as long as the timeout of this particular priority - 1 minute.
Example 2 - Default Priority Job
In this case, we will update one field (price) in all 500 products in an e-commerce store. In an actual application, a discount would probably be a separate field but for this example, let's assume there is no such field.
{% background priority: 'default', source_name: 'apply-discount' %}
{% graphql products, table: 'products', field: 'price_cents' %}
query products($table: String!, $field: String!) {
records(
per_page: 1000
filter: {
table: { exact: $table }
}
) {
results {
id
price: property_int(name: $field)
}
}
}
{% endgraphql %}
{% assign prods = products | fetch: 'records' | fetch: 'results' %}
{% for prod in prods %}
{% comment %}Apply 15% discount{% endcomment %}
{% assign newPrice = prod.price | times: 0.85 | floor %}
{% graphql updated, prod_id: prod.id, new_price: newPrice, table: 'products', field: 'price_cents' %}
mutation update_prices($new_price: Int!, $prod_id: ID!, $table: String!, $field: String!) {
record_update(
id: $prod_id
record: {
table: $table
properties: [{ name: $field, value_int: $new_price }]
}
) {
id
}
}
{% endgraphql %}
{% endfor %}
{% endbackground %}This operation probably will not take more than one minute, but because this is not a time-sensitive task, we will let it run in the default priority queue.
Example 3 - Long-Running Job
When you need to do something very time-consuming, use the
{% background priority: 'low', max_attempts: 3, source_name: 'long-running-job' %}
{% comment %}
Code
{% endcomment %}
{% endbackground %}