Building performant Retool apps

A basic guide and some suggestions for keeping your Retool apps in tip top shape. Building apps in Retool is a lot like building a traditional web app (just a lot easier!), so best practices align in both.

Fundamentals

Performance is app specific, query specific, and even user specific. Apps can be slow for many reasons, and that slow performance isn’t always reproduce-able. As you would when debugging your own application, try and think about the full surface area. What device are you using? Where are your servers located and what’s your network speed? Has anything changed on your end recently?

Retool will add some degree of overhead to your baseline query performance. While Retool usually only adds ~150ms of overhead to your queries themselves (we’re working on reducing this), the process of downloading results, transforming them with JS, displaying them in the UI, and recalculating dependencies can take significantly more time than directly running the query on your database or API. Instead of comparing query times in Retool to those in your SQL or API client, a fairer comparison would be to other web apps or admin UIs handling a similar scale of data.

The Retool team is actively working on improving application performance. Retool is a young product with a couple of rough edges, but it’s more than possible to build highly performant web apps on the platform today. We’re actively working on making this easier.

Best practices

Limit queries that run on page load. Retool allows you to run queries on page load, and add an optional delay. While this can be helpful to make sure your dashboards are always carrying fresh data, it can overload your app when it starts up. Limit the number and size of queries you run on page load, and consider having them run when inputs change or manually.

Use query caching to your advantage. Retool allows you to cache query results. Just click on the “advanced” tab in your query editor for a given query and select the checkbox. You can also cache queries across users in your organization’s advanced settings page (/settings/advanced). If you’re running large analytical queries, or in general don’t need constantly up to date figures, consider using caching to help improve performance.

Limit the number of components and queries in your app. As with any web app, the more components and queries you have – especially when they’re interactive – the harder your app will have to work to be performant. Try and avoid superfluous component sets when possible, and merge your queries to avoid the N+1 problem.

Another best practice here is to prefer multiple smaller apps to one large app. If you don’t need all of your functionality in a single screen, consider a few more use case specific Retool apps, and link between them with Button components that open other Retool pages. You can use the Query Library to write your queries in a central place and then re-use them across multiple applications.

Avoid overloading the frontend with large datasets. Loading 500K rows of data into any frontend is going to push the limits of what it was designed to do. Unless you need massive data in the browser for specific types of visualizations, try and avoid it, and instead, apply transformations and aggregations at the query level. Retool customers often use server side pagination in their Table components to get around this problem.

Minimize long dependency chains. Retool builds and maintains a dependency graph of each application so you can write Javascript in {{ }} anywhere. The deeper and more complex that chain is, the longer it takes to re-calculate and populate when the model gets updated. To whatever degree you can, try and keep your references shallow and avoid having too many components rely on properties of other components.

Move complexity to the backend when possible. The ability to write Javascript anywhere in Retool can lead to frontend sprawl, where developers avoid adding functionality to the backend because it’s easier to do on the frontend (at least temporarily). Retool is best used as a frontend building on top of a well-designed backend – whenever you can, move complex transformation logic to your APIs to keep your app performant.

Troubleshooting query runtimes

Query runtime statistics are available on hover after the query has runQuery runtime statistics are available on hover after the query has run

Query runtime statistics are available on hover after the query has run

Total time: After a query has been run in an app, it will display the total runtime of that query next to it's name in the query editor. Hovering over this runtime will open up a popover menu with a breakdown of query performance

Prepare query: The amount of time that it takes to calculate all inputs to a query in the Retool frontend, format the request, and send it to the Retool backend to then proxy the query using your securely encrypted resource credentials.

Backend: This is the time spent inside of Retool's backend, executing the query inside of your database or API, and transferring data to and from Retool's backend. To improve this runtime consider reducing query complexity, response size, and running Retool on-premise to locate the retool backend closer to your datasource.

  • Execute resource: The time that it takes for Retool's backend to prepare the query, send it to your datasource, and receive the response. Network latency to and from Retool's backend server from your datasource will impact this, as well as query runtime inside of your resource. Larger response sizes will require more bandwidth and be more heavily impacted by the quality of the network
  • Transfer data: The time that it takes to transfer the prepared query to Retool's backend from the frontend, and to transfer the returned result back to the frontend.

Frontend: The time spent processing the query returns inside of your Retool app itself. To improve this runtime consider the efficiency and complexity of your app and how the query return will be processed.

  • Handle response: The time it takes to receive the query response in the frontend and populate the query's data property in the app's data model.
  • Transformer: The time spent processing the query's original data property using your attached Javascript transformer and returning a result. This statistic will only show if the query has it's attached query transformer enabled. More complex transformers with many recursive iterations or additional data references will take longer to process.
  • Post-processing: The time that it takes to update all dependencies inside of the Retool app that reference properties in this query. For example, a table component's data property of {{query2.data}}. You'll notice this time increase as you create more complex apps with a larger dependency graphs that needs to be updated with the new values.

Response size: The total size of the payload returned from your query. As this increases, you'll notice an increase in both frontend and backend processing times due to the larger return.


Did this page help you?