App performance best practices

As your Retool apps become more complex and interact with an increasing number of data sources, it's important to monitor performance and make improvements where needed. Performance issues can happen for any number of reasons and can be difficult to replicate, especially when they involve external factors.

Follow these practices to identify, resolve, and prevent performance degradation and keep your apps operating as efficiently as possible.

Investigate external factors

Apps are a collection of components that query data from third-party services. Users interact with apps over the internet using a web browser. It's often useful to work backwards and rule out user issues first (internet connectivity issues, browser not up-to-date, poor Wi-Fi coverage, etc.), followed by potential service disruption with any connected API or database.

Break up large apps into smaller ones

The more components and queries an app contains, the more work you need to do to maintain them. Break up larger apps that perform several distinct but separate functions into multiple apps that can focus on specific needs.

You can link to other apps using components like Navigation or Button so that users can still quickly access other apps when needed. You can also use modules to create larger apps that combine separately developed apps together, streamlining maintenance.

Allow for additional query overhead

Retool queries add a small amount of overhead to queries (approximately 150ms) when compared to a making an API request or querying a database directly. This additional overhead allows Retool to:

  • Download results
  • Transform data using JavaScript
  • Assign values to relevant components
  • Calculate further dependencies

This overhead shouldn't have any noticeable affect and may only be apparent when compared to a direct request.

Separate query logic to reduce round trips

If you have many similar queries (e.g., multiple queries for the same database table), consider using query JSON as SQL or JavaScript transformers and reduce the number of requests sent to your resources. These allow you to query a resource once but then further manipulate or transform the data as needed.

Limit running queries on page load

Your apps can run queries on page load with an optional delay. While this can be helpful to make sure users always see the most up-to-date data, they cannot fully interact with the app until those queries are complete, making the app feel unresponsive for a short time. 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

You can cache query results for a specified period of time to reduce the number of queries to a resource. You can also cache queries for users across your organization. If you’re running large analytical queries, or don't need immediate data, consider using caching to help improve performance.

Share queries across your organization

Use Query Library to write queries that can be re-used across multiple apps. This allows you to manage queries centrally and make improvements once rather than per-app.

Avoid querying large datasets

Rendering thousands of rows of data into a table will impact browser performance. Instead of loading large amounts of data, consider transforming or filtering data in the query. Many APIs support pagination so you can filter responses to only data you need. The Table component supports using server-side pagination to allow for more specific data requests.

Minimize long dependency chains

You can reference other queries and components almost anywhere using JavaScript. To enable this, Retool builds and maintains a dependency graph for each app. The deeper and more complex this becomes, the longer it takes to update this information. Avoid deep references to other components that result in long dependency chains.

Put complex logic in the Retool backend

Overuse of complex JavaScript can impact the Retool frontend (the part of the app with which users interact). If you need to perform complex logic or querying of data, avoid doing this just with JavaScript. Put this logic into the Retool backend (the part of the app that interacts with resources) to handle as much of it as possible.

Consider deploying Retool on-premise

You can self-host Retool on your own infrastructure. You can run Retool in your own virtual private cloud (VPC) or behind your virtual private network (VPN), allowing the Retool backend to be located much closer to any data sources you use.

Debug query performance

Queries display the total runtime in the query editor once they complete. Place the cursor over the runtime to display a popover menu with a breakdown of performance.

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

Query performance includes the following information:

  • Prepare query: The time taken to calculate all inputs to a query in the Retool frontend, format the request, and then send it to the Retool backend to make a request to the resource.
  • Backend: The time taken by the Retool backend to execute the query with the resource, and transfer data to and from the Retool backend.
    • Execute resource: The time taken by the Retool backend to prepare the query, execute it with the resource, and receive the response. Network latency between Retool and the resource, along with the time taken by the resource to perform the request, can impact the time taken. Larger queries and responses require more bandwidth and can be more affected by network quality.
    • Transfer data: The time taken to transfer the query and results between the Retool backend and frontend.
  • Frontend: The time taken by the Retool frontend processing the query results.
    • Handle response: The time taken to receive the query response in the Retool frontend and populate the query's data property in the app's data model.
    • Transformer: The time taken processing the query's original data property using your attached JavaScript transformer and returning a result. This statistic only appears if the query has a query transformer attached and enabled. More complex transformers with many recursive iterations or additional data references take longer to process.
    • Post-processing: The time taken to update all dependencies inside of the Retool app that reference properties of this query. For example, a Table component that displays {{query2.data}} or a Text Input component that displays {{ query2.data[0]name }}. The more dependencies to update, the longer this can take.
  • Response size: The total size of the payload received. Larger payloads result in longer processing times in both the Retool backend and frontend.