Nanoflows versus Microflows: when to use which and why? Or perhaps even a combination of the two.
Mendix documentation’s definition of microflows and nanoflows is as follows:
“Microflows allow you to express the logic of your application. A microflow can create and update objects, show pages, and make choices. It is a visual way of expressing what traditionally ends in textual program code.”
“Nanoflows are similar to microflows in that they allow you to express the logic of your application. However, they have some specific benefits (for example, they run directly on the browser/device and can be used offline). Furthermore, most of the actions run directly on the device, so there is also a speed benefit for logic that does not need server access.”
Nanoflows were introduced a few major @Mendix versions ago. Over the years, they have gained more capabilities. They are the only method of adding logic to offline-first applications. They have some fantastic options to speed up interactions with your application on online-capable apps, both on mobile and in other formats.
They are, however, not a magical solution to gain performance. When misused, they can cause more harm than good to the experience of your application.
That's why it's essential to understand the differences in usage between microflows and nanoflows.
Microflows are a trustworthy option when executing any logic. They are the only option in the following scenarios.
Circumvent access rules
Microflows are executed without access rules by default. You define the allowed roles to execute the microflow, and anyone with one or more of those roles can execute the microflow.
This allows you to work around entity access, which could be helpful when you do not want users to create/delete/change entities based on XPath and role-based access. You may apply extensive business logic via the microflows and prevent users from creating/deleting/changing the entities via the client API.
If you enable entity access, all of the rules from entity access apply. This could be a nice extra layer of security, especially when dealing with a multitenant application.
When triggering multiple database activities (or any if possible)
Database actions, by default, require interaction with the server. Unless you are dealing with an offline mobile application, the local database will handle some database activities and only synchronise upon request. However, if you want to execute multiple database activities such as retrieves, commits, and deletes, you must execute them in a microflow. Not doing so will result in multiple network requests from the client to the server, negating any advantage a nanoflow would have for the user executing them.
The exception being entities that are purely none-persistent. You may execute any above activities in a nanoflow without any performance penalty due to a network request. You could also try retrieving anything already returned to the client by association. And changing an object without a commit is, of course, perfectly fine to execute in a nanoflow.
For activities not supported by nanoflows
Any activities not supported in nanoflows will, of course, require a microflow to execute them.
The following activities, therefore, are microflow-specific:
For long-running processes
You want to avoid holding up the client when executing long-running processes. Preferably, you do this on the server where multiple threads deal with these processes and can report back to the user asynchronously. Often, these types of processes require microflow-specific activities or are database-heavy anyway.
For heavy and / or complex processes (that you want to test)
While you could call sub-nanoflows, there isn’t an out-of-the-box solution to unit test nanoflows. If you want to keep your complex processes testable and maintainable, you will need to consider using a microflow. On top of that, heavy and complex processes often involve microflow-specific activities and/or loads of database interactions.
Nanoflows are executed at the client. This could be as part of a native mobile application—it even works when offline—or a web application. When built correctly, they do not interface with the server or have minimal interaction with the server.
For client-only activities
Nanoflows run on the client, which means they may execute JavaScript just as Microflows execute Java. They are also capable of interacting with the client device, such as retrieving GPS coordinates, opening a new browser window, or even sending a text message. These client-only activities have been bundled in the Nanoflow Commons module and are available on the Mendix marketplace.
Some of these activities (including those from the Nanoflow Commons module) are:
For simple processes
Nanoflows are excellent for simple client-side processes, such as changing a boolean used to hide/show elements on the page via conditional visibility. Apply basic validations (make sure to revalidate server-side always).
Or, as a data source, sort a small list before showing it in a grid or list view. Of course, this is only for non-persistent entities or client-side data retrieved by association.
To execute JavaScript
All Nanoflow Commons module activities are based on JavaScript, often powered by React or a React-enabled library. Executing these can only happen on the client side through a Nanoflow. This gives you advanced usage options to interact with a users device. Or execute logic on the browser side that might otherwise need an entire widget. An excellent example is starting the webcam.
For offline first native applications
When your application has to operate offline, it can only rely on nanoflows for its logic. This limits you as you can’t do everything you could on the server, but it also opens up a whole new world of possibilities that we did not have before nanoflows were introduced.
Many actions you use in nanoflows require some level of understanding of JavaScript. Especially the more advanced actions driven by JavaScript actions. But that does not mean that they should be avoided altogether. The Nanoflow Commons module and other modules in the Mendix marketplace have excellent code to achieve what you cannot do on the server side.
Using the information listed above, you should be able to weigh your options properly regarding when to use nanoflows and microflows.
A hybrid approach could be an excellent option for combining the best of both worlds. Some client-side logic could be executed in preparation for execution on the server side, and then the results could be dealt with by executing some more client-side logic.
For example, many widgets allow you to trigger an action but do not allow you to set a confirmation message or even a progress bar. When executing long-running microflows, you want a progress bar to inform the user. Using the example above, you could still show the progress bar by having a nanoflow called the microflow after the progress bar is triggered. Then, when the microflow is done or fails, you simply hide that progress bar again.
This is a relatively simple example, but there are many more combinations for which a hybrid approach could be useful.
Examples of both nanoflows and microflows
There is a time and place for both microflows and nanoflows. I would find it awesome if Mendix just decided for you. Only when you really want to, you may override its decision to execute something server-side, client-side, or hybrid.
Until Mendix becomes smart enough to make that decision for us, you may use everything I wrote in this blog to make that decision yourself.
Keep in mind that even the best practice recommendations are not always right. Do not just convert your microflow into a nanoflow and change all the entity access, as this will result in errors.