9 Essential Performance Best Practices: Turbocharge Your Appsmith Apps
Appsmith drastically streamlines development, but even the best low-code tools are no substitute for software engineering best practices. This includes additional best practices that are due to Appsmith’s unique architecture.
This article explains these performance aspects of Appsmith’s architecture, some of the common mistakes that lead to slow applications, and our recommendations for making the most efficient Appsmith apps possible.
At Appsmith, we're obsessed with performance
The performance of Appsmith is one of our highest priorities. But because developers have the freedom to build whatever they want on Appsmith, a large portion of app performance is out of our hands. Your app’s performance is a combination of the Appsmith platform's overhead, your app’s client-side overhead, and the server-side overhead of your datasources.
Improving the performance of the Appsmith platform is our responsibility. In fact, we have an entire team (the performance pod that I work on) dedicated to continually trying to improve performance every single sprint.
You can expect that, in general, the Appsmith platform will continue to become more performant after every new release. In fact, we had a recent case where we saw a 100% improvement in first-page load times for our new releases compared to the releases from a year ago. These small, continuous improvements really stack up over time.
For this reason, we always recommend upgrading your Appsmith version if you are self hosting. (If you’re using the Cloud version, you're always on the latest version!) We release a new version every two weeks and always make sure new versions are backwards compatible.
The release log (published in GitHub) is where users can see which is the latest version of Appsmith, bug fixes, enhancements, etc. The release log is also available in the Appsmith dashboard in the workspace view.
While having an up-to-date Appsmith instance is important, it's also important to understand how the client-side overhead and server-side overhead of your app are affecting performance and the best practices to improve each one.
Optimizing the client side of your app
The client side is where you have the most control over the performance of your app. Client-side performance is (sometimes significantly) affected by factors such as the number of widgets and the complexity of bindings, as well as the size of API and database results.
Here are some of the best practices on the client side that we recommend to mitigate any performance hits.
1. Limit the number of widgets on a single page
Appsmith applications are loaded on a per-page basis, not a per-tab or per-application basis. This means that only the widgets associated with the current page are loaded (not widgets from the same application but a different page). Also note that during a page load, all widgets on the current page are loaded, including widgets that are not visible. Therefore, each additional widget on a page decreases performance and it’s important to reduce them when possible.
Appsmith applications are broken apart by page. You can navigate between different pages of your application with the pages menu on the top left of the editor.
Because of this, we recommend building your apps with one concept per page. As long as there aren’t too many widgets on a single page, your app can be as big as you want without harming performance. Splitting up content also promotes one of the most important goals of UX design: simplicity. This way, it’s much easier for users to understand the purpose of each page and navigate between them without getting overwhelmed.
When splitting your content, we recommend using pages instead of tab widgets whenever possible. It makes sense to use tabs when the content is closely related (same datasource) but can be categorized into different front-end filters or views. On the other hand, it makes sense to use pages when the content represents distinct workflows or processes that are independent of one another (different datasources).
And if the separate pages of your app are loosely related, you can seamlessly navigate between them with navigateTo()just like you can navigate across multiple pages on your website with hyperlinks (instead of stuffing all the content on your site into one web page!). If there are specific variables you need to share across these pages, you can use our key-value store to share a common context across multiple pages within your application.
Limit the number of widgets that are hidden or only conditionally visible (like modals) on a single page. It’s also important to avoid nesting too many widgets within others. The two biggest culprits here are usually overly-complicated tabs (we covered this above) and forms. (We have seen some apps with as many as 50 fields in a single form!)
While designing your app, it’s easy to forget about widgets that are hidden, conditionally visible, or nested within other widgets. Fortunately, you can always see all of the widgets on a single page while editing applications in Appsmith with the widget pane on the left-hand side.
2. Optimize JavaScript code
With Appsmith, you have complete freedom to implement any data structures and algorithms that you want in your JavaScript code (through JS bindings and JS Objects). But just as with any programming language, the time and space complexities of these algorithms and data structures directly affect app performance.
That’s why it’s so important to choose efficient data structures and algorithms for processing and manipulating data. It’s best to use libraries like lodash most of the time as they’re heavily tried and tested, and implement your own data structures and algorithms only when necessary as they may be less efficient. Another benefit of relying on trusted libraries is that you don’t have to write logic for problems that already have accepted solutions in the community.
You can also use JavaScript functions like performance.now() or console.time() to profile and analyze the performance of your code in your browser's developer console, to see exactly which sections of your code are responsible for most of the latency.
3. Make efficient use of Appsmith’s key-value store
Appsmith’s key-value store acts as a wrapper around JavaScript’s local storage functions to persist data: localStorage and sessionStorage. While this key-value store is vital for sharing the context of an application across pages in Appsmith, misusing it can have a performance impact.
In cases where multiple related variables need to be stored in local storage, we recommend batching multiple storeValue() calls into a single storeValue() call. This will mitigate the overhead as the wrapper function only has to be called once to store one large object instead of multiple times to store many smaller objects.
For example, if you’re looping a hundred times to store a new value in Appsmith’s store, it would be more performant to store those variables in a single JS object or array and then store the entire JS object in the object store once at the end.
You can also use JS Object variable mutation when you’re keeping objects purely on the client side and won't be passing them to the server side, as it has better performance than storeValue().
4. Review page load queries
You can set certain queries and JS Object functions to trigger on page load. However, it’s possible for them to become orphaned during development, leading to unnecessary operations on page load, which negatively impacts page performance.
If your page load times are too high, it’s a good idea to review and disable queries that don’t need to run on page load to maintain optimal performance. In general, it’s also a good idea to favor lazy loading over eager loading by fetching only the data that needs to be displayed to users on screen and defer fetching other data until it is needed.
5. Offload heavy client-side computation to the server
The performance of code on the client side is obviously heavily dependent on the client's processing specifications. More powerful systems will result in faster app performance while less powerful systems will result in slower app performance.
Keeping this in mind, when designing apps targeted for low-performance devices such as mobile phones, ensure that the apps are not client-heavy. Instead, consider offloading as many complex computations as possible to the datasources you use to maintain optimal performance.
6. Disable unnecessary browser extensions
While it’s not possible to control the browser environment for your end users, in order to make your own development less painful, you can disable your own browser plugins that might be interfering.
To significantly improve performance, you can disable browser extensions, especially developer tools like React and Redux plugins, since we enable Redux dev logging in production to better debug user systems. This helps ensure that your browser remains light and responsive during development.
Optimizing the server side of your app
How well you’ve optimized your client side doesn't really matter if you have a poorly-optimized server side. With that in mind, let's look at some of the best ways we’ve seen to optimize the server side of your app.
1. Profile server calls
If the latency in your application is coming from slow queries on the server side of your application, nothing you do on the client side will help. That’s why it’s so important to be able to identify exactly where the issue is.
You can identify slow server calls in the Query pane of the Appsmith editor, which shows how long each call takes. If you have custom client-side JavaScript code that makes server calls, you can also use the previously mentioned performance.now() or console.time() functions to analyze the performance of different code segments.
Depending on which datasource is responding slowly, there may be database profilers to help you understand how the query is actually running behind the scenes. That can help you further drill down on sources of latency within the steps of the query itself. Some popular profilers are the MongoDB database profiler and the SQL Server profiler. Profiling is important, but after you’ve identified the slow queries the most important thing is to actually optimize them!
2. Optimize queries
There are well-known best practices like implementing indexes for appropriate columns when optimizing SQL database queries. However, the best practices to optimize queries vary wildly across different datasources, so you'll have to refer to documentation for specifics. You can also use AI tools like ChatGPT to help you write or refactor your queries. (But make sure you test their output, as the models aren’t perfect!)
The size of a query response (even if it’s the right data) also affects performance. You should break up data into smaller, more manageable batches with server-side pagination. Appsmith supports pagination natively as long as your datasource does.
It’s also possible that certain third-party datasources just implement their queries inefficiently on the back end or have subpar infrastructure to serve requests. In this case, the only solution is to switch to a different provider.
3. Upgrade server specifications
If you've optimized every facet of your front and back end, and you're hosting your own infrastructure, your last resort may simply be more powerful hardware. That might mean upgrading your on-premises hardware or increasing the resources available to your cloud instances.
Appsmith streamlines development without sacrificing performance
Appsmith allows you to move orders of magnitude faster when building your applications — but it's important to remember that you can still build inefficient apps if you don't build with performance in mind (just like you can with any other programming platform, framework, or language).
If you're building mission-critical apps where performance, reliability, and high availability are required or trying to scale Appsmith across your entire company, contact us to see how we can help with more in-depth enterprise support.