> For the complete documentation index, see [llms.txt](https://docs.ninox.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ninox.com/ninox-scripting/automate-your-workflows/automations/optimize-the-performance-of-your-app.md).

# Optimize the performance of your app

Learn how to optimize Ninox app performance with efficient queries, triggers, and data handling.

The following best practices are key recommendations that have proven effective. They address common pitfalls such as inefficient data access, unwanted trigger cascades, and loop-intensive computations. Consistently applying these guidelines can help reduce load times and conserve system resources.

#### **Optimize initial views for large tables**

When working with large tables, filter the initial view to display only a relevant subset of records—specifically, only those that are needed. This significantly improves load performance and enhances the user experience.

#### **Avoid conflicting or circular triggers**

Ensure that triggers are designed to operate independently and do not interfere with one another. In particular, avoid configurations that may cause circular references or unintended trigger loops, as these can lead to unpredictable behavior and performance issues.

#### **Use select statements sparingly**

Only use `select` statements when absolutely necessary. If references to the target table already exist, leverage those instead. For accessing related data in sub-tables, prefer dot notation over `select` statements to improve performance and maintain clarity.

❌ Avoid:

```none
sum((select invoice_items where invoice = i).total)
```

✅ Use this instead:

```none
let me := this;
sum((Invoice_items[invoice = me]).total)
```

#### **Minimize select statements in function fields**

Avoid using `select` statements within function fields displayed in table or form views whenever possible. If a `select` statement is required, use the `where` clause for defining conditions instead of square bracket syntax `[...]`.

#### **Avoid repeated select executions**

When a `select` statement is required in a script, execute it only once and store the result in a variable. Reuse this variable to access multiple fields as needed. This approach enhances performance and reduces redundant database operations.

#### **Avoid select statements in nested loops**

Wherever possible, refrain from using `select` statements within nested loops. This pattern can lead to significant performance degradation due to repeated database access. Instead, consider retrieving data in advance and using cached data.

#### **Prefer writing static values over repeated formula evaluation**

Instead of recalculating formulas dynamically each time ("on the fly"), consider writing static values to data fields using triggers, provided it is appropriate and beneficial. This reduces processing overhead and improves overall system efficiency.

#### **Optimize searches in table views from dashboard form views**

When performing searches in table views via a form view or page, define all variables using `let` before executing the search with a `select` statement. To optimize performance, limit the results to avoid loading unnecessary data. Additionally, use the `not` command to properly handle empty search fields and ensure accurate filtering.

```none
let mySearch := 'Project search';
select projects where (not mySearch or project_name +
     concat(project_staff.choose_person.full_name) like mySearch) from 0 to 100
```

#### **Avoid storing large text blocks in text fields**

Refrain from storing large content directly in text or HTML fields, for example, CSV files, Base64 files, or JSON payloads for API calls. Since Ninox logs every change, this can lead to an excessively large change history and impact performance. A better approach is to generate such content using `createTextFile()` and store it as an attachment.

You can then access the file using the API or the following function:

```none
let response := http("GET", Sharelink);
text(html(response.result))
```

#### **Use indexing selectively**

Apply indexing thoughtfully only to fields that are frequently searched and benefit from faster access. Fields with limited value sets, such as Yes/No fields, typically do not require indexing.\
Learn more [here](/ninox-scripting/automate-your-workflows/automations/index-fields-to-speed-up-filters-and-searches.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.ninox.com/ninox-scripting/automate-your-workflows/automations/optimize-the-performance-of-your-app.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
