Deployment setup#

Running an application in production has many additional requirements compared to running it in a local environment. Data sources are often not in the same place as the application and the application’s health and logs need to be monitored.

In order to help prepare the application for deployment and to get the most out of it, here are some good practices to follow when creating and configuring an Atoti application.

Port#

The port the application will be served at should be pinned using the atoti.Session()’s port parameter. This is the only port which needs to be opened (or mapped to the container) for the application to work. If the hosting platform sets the $PORT environment variable to the port to which the application should bind, the session can be configured with {"port": os.environ["PORT"]}.

One way data flow#

We recommend setting up the application so that it never modifies its data directly. A good practice is to modify the source data before loading it in Atoti, and then create watchers for the application to ingest the changes made to the source data. See how to Watch local files.

Setting up data flow like this has two main advantages:

  • Changes are persisted, which means that if the application restarts for any reason, the data contained in the Atoti session will be the same before and after the restart.

  • If multiple instances of the application need to be deployed (behind a load balancer for example), it’s easier to ensure that all the applications contain the same data by having them read the same files, rather than trying to apply the same changes to each instance.

Likewise, if security has been set up on the session, we also recommend keeping the roles and restrictions in a file and using a watcher and atoti.Session.security to keep the roles in the session up to date with those in the file.

JDBC user content storage#

If there will be multiple instances of the application running, the users’ saved dashboards will need to be made available to each of the instances. The best way of doing this is to deploy a SQL database to host the users’ data and configuring each instance to connect to this database. Using a fully managed service to do this saves the hassle of managing backups and scaling of the user content storage.

Use atoti.UserContentStorageConfig to back the user content storage with this SQL database.

Java options#

JVM options can be passed to the session to configure the Java environment to best suit your needs.

Memory#

The underling Java process uses two kinds of memory, heap and off-heap. The sum of memory allocated to both of these types of memory must not exceed your system’s physical memory.

By default, we restrict the amount of memory that the JVM uses to avoid using to much of your system’s resources. While this can be useful in the development phase, when moving to production you usually want to dedicate a large portion of the server hosting the application’s resources to the application itself.

Heap size#

The Java heap is the amount of memory available to the application for object allocation. This portion of memory used by the Java process is subject to garbage collection. The following parameters can be set:

  • -Xmx: maximum Java heap size, the higher this value, the more memory will be available for your application.

  • -Xms: minimum and initial Java Heap size, setting this does not limit the maximum Java heap size. Naturally, the value of Xms must be smaller than the Xmx value if both are set.

  • -XX:MaxRAMFraction (or -XX:MaxRAMPercentage if you prefer), percentage of your resources to dedicate to the Java Heap. This also requires the -XX:+UnlockExperimentalVMOptions to be passed in order to be used, and shouldn’t be used in conjunction with -Xmx.

Off-Heap size#

The underlying Java process of Atoti uses off-heap memory to store its data (i.e. anything loaded into a atoti.Table). Off-heap memory is allocated outside of the JVM, and not managed by it. The underlying Java process uses off-heap memory to do most of its long-lived allocations which reduces the pressure on the Garbage Collector.

The most important parameter to know is -XX:MaxDirectMemorySize (Off-heap memory is also referred to as Direct memory). This parameter allows to choose the maximum amount of off-heap storage which can be used by the application. This should be big enough to hold all of the application’s data.

If -Xmx is set and -XX:MaxDirectMemorySize isn’t, the direct memory limit will be equal to the heap size. For example, if -Xmx5g is used, the application’s maximum memory usage can grow up to 10Gb.

This guide provides more advanced information on optimizing the JVM for production applications.