Payload is designed with performance in mind, but its customizability means that there are many ways to configure your app that can impact performance.
With this in mind, Payload provides several options and best practices to help you optimize your app's specific performance needs. This includes the database, APIs, and Admin Panel.
Whether you're building an app or troubleshooting an existing one, follow these guidelines to ensure that it runs as quickly and efficiently as possible.
The proximity of your database to your server can significantly impact performance. Ensure that your database is hosted in the same region as your server to minimize latency and improve response times.
If a particular field is queried often, build an Index for that field to produce faster queries.
When your query runs, the database will not search the entire document to find that one field, but will instead use the index to quickly locate the data.
To learn more, see the Indexes docs.
There are several ways to optimize your Queries. Many of these options directly impact overall database overhead, response sizes, and/or computational load and can significantly improve performance.
When building queries, combine as many of these options together as possible. This will ensure your queries are as efficient as they can be.
To learn more, see the Query Performance docs.
When querying data through Payload APIs, the request lifecycle includes running hooks, access control, validations, and other operations that can add significant overhead to the request.
To optimize your APIs, any custom logic should be as efficient as possible. This includes writing lightweight hooks, preventing memory leaks, offloading long-running tasks, and optimizing custom validations.
To learn more, see the Hooks Performance docs.
If your validation functions are asynchronous or computationally heavy, ensure they only run when necessary.
To learn more, see the Validation Performance docs.
When building custom components in the Admin Panel, ensure that they are as efficient as possible. This includes using React best practices such as memoization, lazy loading, and avoiding unnecessary re-renders.
To learn more, see the Custom Components Performance docs.
Use Block References to share the same block across multiple fields without bloating the config. This will reduce the number of fields to traverse when processing permissions, etc. and can significantly reduce the amount of data sent from the server to the client in the Admin Panel.
For example, if you have a block that is used in multiple fields, you can define it once and reference it in each field.
To do this, use the blockReferences option in your blocks field:
Ensure that you do not instantiate Payload unnecessarily. Instead, Payload provides a caching mechanism to reuse the same instance across your app.
To do this, use the getPayload function to get the cached instance of Payload:
Making direct database calls can significantly improve performance by bypassing much of the request lifecycle such as hooks, validations, and other overhead associated with Payload APIs.
For example, this can be especially useful for the update operation, where Payload would otherwise need to make multiple API calls to fetch, update, and fetch again. Making a direct database call can reduce this to a single operation.
To do this, use the payload.db methods:
To prevent unnecessary database computation and reduce the size of the response, you can also set returning: false in your direct database calls if you don't need the updated document returned to you.
If your front-end imports from @payloadcms/ui, ensure that you do not bundle the entire package as this can significantly increase your bundle size.
To do this, import using the full path to the specific component you need:
Custom components within the Admin Panel, however, do not have this same restriction and can import directly from @payloadcms/ui:
Everything mentioned above applies to local development as well, but there are a few additional steps you can take to optimize your local development experience.
Add --turbo to your dev script to significantly speed up your local development server start time.
By default, Next.js bundles both server and client code. However, during development, bundling certain server packages isn't necessary.
Payload has thousands of modules, slowing down compilation.
Setting this option skips bundling Payload server modules during development. Fewer files to compile means faster compilation speeds.
To do this, add the devBundleServerPackages option to withPayload in your next.config.js file: