10 tips to increase speed and performance in Retool

In this article, we summarize 10 tips to help you speed up your Retool apps and ensure they stay performant.

10 tips to increase speed and performance in Retool

Developing on Retool means you can build efficient business software much faster, but sluggish internal apps and long loading times can still slow your teams down. In this article, we will dive into some of the reasons why your apps might be loading slowly, and offer 10 great tips for making your Retool apps as performant and efficient as possible.

Let’s jump in!

First step: evaluating your app performance

You may have noticed a recent addition to the Retool Debugger tool in the form of the ‘Performance’ tab. This Performance page is a great addition that summarizes the efficiency of your apps, offering some key statistics to help you understand what’s going on.

The Retool debugger showing performance and query load time for an app
Internal app performance statistics in Retool 


The page grades your query stats and app size, looking at query runs, speed and size, and app size, judged by the number of components and code blocks, HTML elements, and dependency graph nodes. This is a great place to start to evaluate the performance and speed of your apps.

If you’re finding yourself in the red and looking to improve your efficiency score, then luckily for you, we at Bold Tech have great tips and tricks to share for building performant apps that will banish that loading spinner for good (or at least, help you spend a lot less time with it).

Generally, our tips can be split into three main categories: app infrastructure, optimized components, and query improvements.

📌 Note: Apps can vary hugely in use case and complexity, so these tips might not improve performance in all cases, particularly for large enterprise apps. Nevertheless, they can be used as a basis for experimenting with the factors that affect performance to find a better alternative for your apps.

Build your app infrastructure for better performance

While Retool is generally pretty intuitive for engineers to work with, some proprietary infrastructure elements aren’t always so straightforward. How you build out your Retool apps - especially within a multi-app system - can have a huge impact on their speed and load times. Here are some tips for managing this infrastructure for better performance.

Multi-page apps rather than segmented views in a single app

As your internal tools scale across teams and use cases, you will likely have different pages for different functionality. In Retool, developers often build a single huge ‘app’ that deals with this data in multiple ‘views’, using a component like a tabbed container.

For better performance, we prefer to split these views into separate Retool apps and treat them like pages, linking across them to create a seamless experience.

To explain more, let’s take a typical example.

Think about an Order Manager Dashboard, where one page is an inventory tracker and another page details purchase orders. Many Retool builders are inclined to build both in a single app, using a tabbed container to switch through the different functions. When this app grows, they simply add another tab to the container.

0:00
/
A tab heavy internal application using Retool

This all-in-one app structure means loading a lot of data on the front end and effectively doubling the data loaded as the app deals with both ‘views’ at once, regardless of which is being used. This style can work for smaller apps with light datasets, but performance tends to slow as the app grows.

While it is possible to somewhat rectify this by coding the application to only load data when the view is switched is clicked, Retool still struggles with performance when there are too many components in a single app.

That’s why we recommend this method of building multiple Retool ‘apps’ to represent ‘pages’ instead. This segments the business logic and data being loaded consistently on the front end at any one time, optimizing load time. In essence, this means creating a new ‘app’ for every piece of functionality, which can also lead to better organization in the developer environment and easier permissioning systems.

Apps organised clearly in a folder in Retool


It’s also beneficial for using DRY (don’t repeat yourself) coding principles in Retool. For example, we recommend building a single form page (such as ‘Create new customer’) that is linked to each page where it is needed. This means that the form can be linked more extensively throughout apps (i.e. anywhere it might be needed), but changes only need to be made once to the form. Compare this to making changes when the form is on one tab, in another modal, and a drawer frame on different pages, and you quickly see that this is an optimized way of building.

A form page in Retool
This form can be linked in four different ways on a single page and across multiple apps. We recommend using the breadcrumb component as in the example above to ensure users can head back to the app they were working on. ‌ ‌

To create a seamless multi-app ecosystem, you can use query parameters and local storage to pass information between apps.

We wrote about building in this way extensively in our multi-page app guide, but to summarize why it’s a good idea:

  • Building separate Retool ‘apps’ to function like app pages is much more performant than tabbed view containers since it loads less code and data into the frontend
  • It’s also a better option for DRY principles as repeated functionality such as forms can be created as a single page where they only need to be edited once, thereby reducing maintenance too
  • Managing app permissions for your teams is easier when functionality is segmented into pages, as permissions can be drawn on the Retool ‘app’ level, rather than inside the apps
  • It’s easier to reload logic across your apps as changes will refresh when you navigate back to app pages, since data will typically fetch on app load
  • The drawback of this option is you will need to re-do some queries when separating these apps, and it can create some complexity when passing data between apps

Head over to the guide for more tips on how to build out these multi-page apps performantly.

How to create great multi-page applications in Retool
Retool has just had a boost in speed and power, so switching between applications much more seamless and performant. In this article, we discuss how to make great multi-page applications with optimal performance and effective UI.



Use pre-loaded JavaScript for complex business logic

If your app uses lots of complex business logic that is used consistently across your apps, you can use pre-loaded JavaScript to define this on an app or global level. This avoids the business logic being constantly rerun for different functions and overloading the app.

Using pre-loaded JavaScript for complex functions and business logic also keeps your code clean and DRY (just like your laundry). Any changes are consistent across apps, and bug fixes are easier too.

Preloaded JavaScript in the Retool environment
Preloaded JavaScript maintains clean code

Let’s take an example of a mortgage company. Calculating mortgage rates is incredibly complicated, and takes lots of complex arithmetic on the code level. This is a perfect example of something worth building into preloaded JS on the global level, you can simply call this function from anywhere in your apps, and changes only need to be made once. Another good use case for this preloaded JS is for Regex.


Rethink your use of modules

The principle of modules (i.e. Retool’s reusable component combinations that can be added to multiple apps) is great, and this might be another option you’d consider for more reusable code.

They are brilliant when creating simple reusable groups of components and in particular navigation bars. We would always recommend using a module to create a consistent navigation bar across your apps in Retool.

A navbar module in Retool
Consistent navigation bar in Retool is created using modules

But, unfortunately, Retool’s modules do have some runtime issues and are generally not yet performant enough to be truly useful in all cases. That’s why generally, we would avoid using modules where possible. While this is not a hard-and-fast rule, we find that modules generally require a lot of technical tweaking to improve performance, and this can get very complicated fast.

As an alternative, we would suggest creating reusable ‘apps’ as we suggest above - for example, you could take your form ‘module’ to create a form ‘page’ instead.

Nevertheless, If you already use modules and want to make them more performant, you can disable queries until the parameter is passed. This is because modules are constantly listening for changes in inputs, which slows computing speed. Setting up clear triggers for these modules to fire queries can help speed them up.


Optimize components and displayed data

Our next set of tips revolves around optimizing the components themselves. Generally, we see the largest leaps in performance when tables are optimized, and more complex components like charts are segmented from apps that are already heavy with functionality.

Filter small datasets on the frontend

Much of the data developers will work with within Retool can be queried with SQL, but that doesn’t always mean that complex SQL queries and filters are a good idea.

While it is possible to filter and manipulate data using SQL just like developers are used to, it does mean that data is constantly being pulled and reloaded from that data connection whenever updates are made or filters are changed, which can slow down app performance, especially for large datasets.

large and complex SQL query in Retool

This can ultimately depend on your use case. Still, for small datasets instead of filtering with SQL, we would typically recommend using the setFilter JS method for setting table filters on the front end.

Setting table filters for small datasets is best with the setFilter JS method in Retool

You can also use a JavaScript query to script all the filters in a single place, and simply trigger this single query when inputs change:

table1.setFilterStack({
filters: [
{ columnId: "id", operator: "=", value: 1 },
{ columnId: "id", operator: "=", value: 2 },
],
operator: "and",
});

See the Retool docs for more info on the filterStack.

📌 Note: this method works best when data volumes are relatively small. When datasets are larger (5000 rows + of data), they may require filtering with SQL or even with pagination instead.


Minimize the amount of components

Too many components, and too many tables in particular will slow your apps down. Like the multi-tabbed container approach we mention above, we frequently see apps with several data ‘views’, pulling in data from the same source into different tables. Unfortunately, this means a lot of these components are slowing the app down in the background. Another common layout we see is the neverending scroll style, where apps continue down the page with lots of components and functionality.

An app with too much functionality as you scroll down the page
Neverending scroll style in Retool

From the developer's perspective, having lots of hidden components also makes it much harder to edit your apps, making it hard to see the true state of your application when developing and debugging it.

One option to solve this is simply separating the functionality across different Retool ‘apps’ as pages, and another is to use dynamic code to alter the view and functionality of the components instead of duplicating them.

Let’s take the example of a button that sets the value from online to offline. One way to build this would be two buttons that switch to hide respectively using JavaScript ternaries. This hiding process slows down the app and would be better set up to switch functionality (and label text) dynamically.

a ternary which alters the button text




Limit charts and complex arithmetic

Another component known for slowing down app performance is the chart component. While Plotly allows for some quite complex chart options, the more complex the data processing, the slower the load. The same goes for statistics that perform any kind of complex arithmetic, these are all additional computational loads on the server side.

Generally, we recommend using JavaScript (especially with libraries like Lodash) to perform calculations on data that has already been loaded into the frontend, since this works much faster than SQL queries to calculate the same.

JS calculations in Retool
JavaScript performs calculations using pre-loaded data to increase efficiency in Retool

To ensure apps load faster, consider putting complex charts and statistics in a separate modal or drawer frame (or even a separate app page), and only set the queries to fire when these are triggered to open.

For really complex logic, we would recommend performing this on the backend before pulling the data into Retool.

Alter queries to reduce data load

Our final set of tips involves speeding up queries, and how to deal with heavy data loads.

Before you get started with improving query performance, start by checking out your query load times in Retool’s built-in debugging tool. You can find this in the bottom right of your canvas.

The query timeline debugger in Retool
Performance improvement starts with checking query load times in Retool


This will be your starting point for what might need fixing immediately, but of course, there is no harm in applying these tips to all queries to ensure the best performance possible.

Minimize queries running at the same time

Queries in Retool default to run on page load, and are often set to update when inputs change. While this is a great option for avoiding stale data, it causes a large load on the server and slows apps. As you can see in the query debugger page above, three of our queries run at the same time. If all of these queries load a large amount of data, this is sure to slow my app down.

To solve this, set up logic that disables queries that are not in the current view, ensuring they are only triggered when needed (for instance, when someone switches views in a container).

Additionally, make sure that queries are only set to rerun when any changes are made that specifically affect that data to avoid queries constantly refreshing unnecessarily.

An example of a query trigger set to "on click" of a button

In this example above, I know that my inventory_all query actually only needs to run when I open a modal that requires this data. So in this case, I can simply set the query trigger to be when ‘on click’ of the button to open the modal.


Only query the data you need

This might seem obvious enough, but since Retool makes it so easy to alter displayed data in components like the table, it’s easy to forget that you aren’t using a large portion of the data you just queried. Instead, make sure that your queries only pull in the data you need for the area of your app that is currently on screen, such as the exact column headers that are needed for your tables that are immediately visible.

You can do this by using SELECT and only listing the column headers you will display in your table. Remember that Retool lists your table schema automatically in the query bar, so you can easily add additional columns to your query when needed.

A simple app and query in Retool
In Retool, use SELECT to list the column headers that will show in a table


If you then display additional data from a selected row in a separate view from your table, you can run this separately on row select. This means that instead of pulling all data from all your tables at once, you only query the exact line of the table you select and pull that data in. To give an oversimplified example, our original table simply pulls in the customer_name and revenue from our database. Then, the second query pulls in the additional data about the id of the selected row, triggered only on row change.

The same above example with additional data displayed in a new row


Nevertheless, this is a balancing act of performance versus reusability. It’s important to not go to the other side of the spectrum and make a query for every single small input. If the data is already loaded in Retool, you don’t need to make more queries. It also reduces overall load on the environment to reuse data from the same query, so it’s important to play with the balance of both in your own apps.


Use of data vs rawData

To reduce the amount of queries in your app, you can leverage the data vs the rawData attributes available in Retool. The .data option will return the transformed values in your data (i.e. the data after it has passed through any JS transformers you included directly in your query), but .rawData will return the data without these transformations.

This means you can use the transformed data for a component like a table, and then use transformed values for your charts, without needing new queries that could slow performance. This is a very small lift and may only have noticeable improvements in niche examples, but can generally be a good way to approach building your apps for better reusability.

You can also use your table data to build your charts, meaning they will already be based on filtered data, and you won’t need to rerun queries.


Paginating large datasets

If you are dealing with particularly large datasets that all need to be pulled into the app, you can use pagination to limit the amount of data loaded into the front end. Retool has built-in options in the table component that make this much easier to build out.

To enable pagination, click the table component and enable the ‘Pagination’ add-on. Limit-offset-based pagination will allow you to query only for the displayed data.

Pagination in a table component
Display of the pagination settings in Retool's table component

Retool provides you with the table.pagination.pageSize & table.pagination.offset attributes to help set these parameters.

Parameter attributes in Retool
Find more details in the Retool documentation.

It does get a little trickier when dealing with filters and searches, however. Typically, you’ll need to use SQL to set up your offset and use WHERE to filter the data according to your filters. This will ensure that data is sorted by these filter conditions before being paginated. Beware, however, that this can be a fiddly process.

Ultimately, it's important to appreciate that there are nuanced trade-offs inherent in each of these choices that go beyond the scope of this article. While these guidelines offer general insights, they are certainly not rigid; every Retool development approach presents its own advantages and disadvantages. Happy building!

💥
At Bold Tech, we specialize in building great internal tools, fast. We are obsessed with building apps that make your teams happier and more productive. In our blog, you can learn all about how to build better business software for more satisfied employees, or get in touch to chat to us about what you're looking to build.

Great! You’ve successfully signed up.

Welcome back! You've successfully signed in.

You've successfully subscribed to Bold Tech Blog.

Success! Check your email for magic link to sign-in.

Success! Your billing info has been updated.

Your billing was not updated.