From 48f1fd6687e4eab502d999923178561652930e6d Mon Sep 17 00:00:00 2001 From: Emir Uner Date: Tue, 6 Oct 2026 17:24:14 +0200 Subject: [PATCH 1/4] Clear documentation about clustered mendix runtime --- content/en/docs/refguide/runtime/_index.md | 11 +---- .../runtime/clustered-mendix-runtime.md | 40 +++++++++++-------- .../runtime/custom-settings/_index.md | 2 +- .../docs/refguide/runtime/runtime-server.md | 2 +- content/en/docs/refguide10/runtime/_index.md | 11 +---- .../runtime/clustered-mendix-runtime.md | 40 +++++++++++-------- .../runtime/custom-settings/_index.md | 2 +- .../docs/refguide10/runtime/runtime-server.md | 2 +- 8 files changed, 52 insertions(+), 58 deletions(-) diff --git a/content/en/docs/refguide/runtime/_index.md b/content/en/docs/refguide/runtime/_index.md index bcdc5bb1c6f..ca4c282ac63 100644 --- a/content/en/docs/refguide/runtime/_index.md +++ b/content/en/docs/refguide/runtime/_index.md @@ -31,16 +31,7 @@ The user interacts with the Mendix Client, which then makes requests, via the [r Passing state from the Runtime Server to the Mendix Client enables the Runtime Server to be stateless, which means that any Runtime Server instance can respond to a request from the Mendix Client. A load balancer decides which Runtime Server instance will respond to a request. When a user session ends, the Runtime Server removes references to that session. -If there is more than one instance of an app, one of the instances is the *Cluster Leader*. This is responsible for Performing database synchronization tasks. It also schedules a number of cluster management activities which can then be picked up by any node. These include: - -* Session cleanup handling -* Cluster node expiration handling -* Background job expiration handling -* Unblocking blocked users -* Executing scheduled events -* Clearing persistent sessions after a new deploy - -More information on multiple instances is in [Clustered Mendix Runtime](/refguide/clustered-mendix-runtime/). +If there is more than one instance of an app, some cluster management activities, such as database synchronization, are coordinated across the instances. For details, see [Clustered Mendix Runtime](/refguide/clustered-mendix-runtime/#cluster-leader-follower). ### External Services diff --git a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md index a3161f06034..40d30d85ec5 100644 --- a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md +++ b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md @@ -27,27 +27,29 @@ This means that a Mendix cluster requires a load balancer to distribute the load ## Cluster Leader and Cluster Followers{#cluster-leader-follower} -Mendix Runtime has the concept of a cluster leader. This is a single node within a Mendix Runtime cluster that performs the initial database synchronization with Domain Model changes and initiates other cluster management activities which can be be picked by any node in a multi-node environment. These are the activities: +How database synchronization is coordinated across cluster nodes depends on how Mendix Runtime is started: -* **Session cleanup handling** – each node expires its sessions (meaning, not being used for a configured timespan) and the cluster leader removes the sessions persisted in the database - * In exceptional cases (for example, a node crash), some sessions may not be removed from the database, in which case the cluster leader makes sure this removal still happens -* **Cluster node expiration handling** – removing cluster nodes after they have expired (meaning, not giving a heartbeat for a configured timespan) -* **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan) -* **Unblocking blocked users** -* **Cleanup unreferenced files** - removing from storage any file documents that have been deleted, replaced, or were never committed -* **Executing Scheduled Events** – legacy scheduled events are only executed on the cluster leader; task queue based scheduled events are executed on an arbitrary cluster node -* **Performing database synchronization after new deploy** -* **Clear persistent sessions after new deploy** – invalidating all existing sessions so that they get in sync with the latest model version +* **Leader-based startup** – Used when the Runtime is started through the administrative API. This is how most managed deployments, including the Cloud Foundry buildpack, SAP BTP, and an on-premises installation managed with the Mendix Service Console, start the app. In this model, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader performs the initial database synchronization with Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. Which node is the cluster leader is controlled with the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide/custom-settings/#commendixcoreisClusterSlave)). +* **Leaderless startup** – Used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect in this model and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below. -The Cloud Foundry Buildpack determines which cluster node becomes the cluster leader and which become cluster followers. +{{% alert color="info" %}} +If you deploy manually using the Mendix Service Console (or another on-premises installation managed through the administrative API), you are responsible for configuring the cluster leader yourself: set `com.mendix.core.isClusterSlave` to `true` on every node except one. This setting does not apply to [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/): it is always started from a configuration file, so it always uses the leaderless startup model, and `isClusterSlave` has no effect there. +{{% /alert %}} + +Besides the startup activities described above, Mendix Runtime nodes also perform the following recurring cluster management activities. These run independently of the leader-based or leaderless startup model, and are not tied to a single designated node: -## Cluster Startup +* **Session cleanup handling** – each node expires its own sessions from its local cache (meaning, not being used for a configured timespan); removing expired sessions from the database is handled by an arbitrary cluster node, based on when each session was last active +* **Cluster node expiration handling** – every node independently removes other cluster nodes that have expired (meaning, not giving a heartbeat for a configured timespan) +* **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan) is handled by an arbitrary cluster node +* **Unblocking blocked users** is handled by an arbitrary cluster node +* **Cleanup of unreferenced files** – each node removes its own file documents that were deleted, replaced, or never committed; cleaning up files left behind by a crashed node is handled by an arbitrary cluster node +* **Executing Scheduled Events** – scheduled events are executed by an arbitrary cluster node; for details, see [Task Queue](/refguide/task-queue/) -Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app the whole cluster is restarted and the cluster leader determines whether database synchronization is required. This means that there will be some downtime when the app is deployed while this is done. +## Cluster Startup {#cluster-startup} -If database synchronization is required, all the cluster followers will wait until the cluster leader finishes the database synchronization. When the database synchronization has finished, all the cluster nodes will become fully functional. +Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app, the whole cluster is restarted, and the database may need to be synchronized with the updated Domain Model, as described in [Cluster Leader and Cluster Followers](#cluster-leader-follower) above. This means that there might be some downtime while this is done. -If no database synchronization is required, all the cluster nodes will become fully functional directly after startup. +Once database synchronization has finished, all the cluster nodes become fully functional. If no database synchronization is required, all the cluster nodes become fully functional directly after startup. ## File Storage {#file-storage} @@ -67,10 +69,14 @@ While running a multi-node cluster, you cannot predict the node on which a micro ### Cluster-Wide Locking (Guaranteed Single Execution) -Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single node Mendix Runtime, this could be guaranteed by using JVM locks. However, in a distributed scenario, those JVMs run on different machines, so there is no locking system available. Mendix does not support cluster-wide locking, either. If this cannot be circumvented, you might need to resort to an external distributed lock manager. However, keep in mind that locking in a distributed system is complex and prone to failure (for example, via lock starvation or lock expiration.). +Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single-node Mendix Runtime, this can be guaranteed with a JVM-local lock, but a JVM-local lock cannot coordinate across the separate JVMs that make up a cluster. + +If the activity can be modeled as a microflow or Java action, you can guarantee it runs on only one node at a time by using a [Task Queue](/refguide/task-queue/) with a cluster-wide scope and a single thread; see [Limitations](/refguide/task-queue/#limitations) in *Task Queue*. Keep in mind that this is an at-least-once guarantee rather than a strict exactly-once guarantee: if the node running the task fails, another node picks it up and reruns it, so the activity should be idempotent. For details, see [Behavior If App Stops Unexpectedly](/refguide/task-queue/#behavior-if-app-stops-unexpectedly) in *Task Queue*. + +For other cases, for example holding a lock for an arbitrary duration around work that cannot be modeled as a queued task, Mendix Runtime does not provide a cluster-wide locking mechanism; you need to use an external distributed lock manager. Keep in mind that locking in a distributed system is complex and prone to failure (for example, through lock starvation or lock expiration). {{% alert color="info" %}} -For the reason described above, the **Disallow concurrent execution** property of a microflow only applies to a single node. +The **Disallow** property in the [Concurrent Execution Section](/refguide/microflow/#concurrent) of a microflow is implemented as a JVM-local lock. It prevents the microflow from being executed more than once at the same time on a single node, but it does not prevent the same microflow from running concurrently on different nodes of a cluster. To guarantee single execution across the cluster, use a cluster-wide Task Queue instead, as described above. {{% /alert %}} ## Dirty State in a Cluster diff --git a/content/en/docs/refguide/runtime/custom-settings/_index.md b/content/en/docs/refguide/runtime/custom-settings/_index.md index 75cdb41ffd6..0ede808041e 100644 --- a/content/en/docs/refguide/runtime/custom-settings/_index.md +++ b/content/en/docs/refguide/runtime/custom-settings/_index.md @@ -53,7 +53,7 @@ The following custom settings can be configured: | ClientCertificateUsages | Only use this when you have multiple client certificates and you want to configure specific certificates for specific servers.
This setting defines which service must use which client certificate. See **NoClientCertificateUsages** if you want to make sure that no client certificate is used for a certain host or web service. The value of **ClientCertificateUsages** must be a comma-separated list of key/value items. A key/value item must be specified as `"identifier": "path to certificate"`.
For web services, use the imported web service name as the identifier.
For REST services, use the host name of the remote server as the identifier.
Please note that any backslash in the path must be doubled. The whole value must be enclosed by braces (`{ }`). For example: {{< figure src="/attachments/refguide/runtime/custom-settings/code_snippet.png" class="no-border" >}} | | | NoClientCertificateUsages | Comma-separated list of host names or imported web service names that should never be contacted using a client certificate. | | | ClusterManagerActionInterval | The interval (in milliseconds) used for performing all cluster manager actions. These are actions such as unblocking users and removing invalid sessions. See [Session Timing Constraints and Defaults](/refguide/tricky-custom-runtime-settings/#session-timing) in *Advanced Custom Settings* for important details about valid values and their relationship to other session settings. | 300000 (5 minutes) | -| com.mendix.core.isClusterSlave | Set to `true` in a high-availability scenario when this is *not* the [Cluster Leader](/refguide/clustered-mendix-runtime/#cluster-leader-follower). The buildpack will usually enforce this setting, but it may need to be set for some on-premises deployments. | `false` | +| com.mendix.core.isClusterSlave | Set to `true` on every node except the [Cluster Leader](/refguide/clustered-mendix-runtime/#cluster-leader-follower) in a high-availability scenario. This setting only applies when the Runtime is started through the administrative API (the leader-based startup model); it has no effect when the Runtime is started directly from a configuration file (the leaderless startup model), which is always the case for [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/). See [Cluster Leader and Cluster Followers](/refguide/clustered-mendix-runtime/#cluster-leader-follower) for details on both models.
{{% alert color="info" %}}Managed platforms, such as the Cloud Foundry buildpack, usually set this for you. For a manual, on-premises installation managed through the administrative API (for example, using the Mendix Service Console), you need to set this yourself on all nodes except one.{{% /alert %}} | `false` | | com.mendix.core.LenientDateTimeParsing | When set to `true`, the `parseDateTime` function will use more lenient parsing, as it did in Mendix 9. For example `parseDateTime("yyyyMMdd", "2021-11-10")` will return `2020-11-01` as a date if this is set to true, which is probably not the intended result.. If set to `false`, which is the default, this example will throw an error as it is expecting `20211110`. It is recommended to not enable this setting to avoid unexpected results. | `false` | | com.mendix.core.SameSiteCookies | The [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) property can be included in all cookies that are returned by the embedded HTTP server. The possible values are `Strict`, `Lax`, and `None`. The default is `Strict`. Setting it to `None` is typically needed only when an application is embedded in an iframe of another application with a different domain. Newer browsers may require the connection to be secure (HTTPS) when set to `None`. If the connection is plain HTTP, then this setting must be changed to `Strict` (recommended) or `Lax`. | | | com.mendix.core.ScheduledEventsCleanupAge | This setting specifies (in milliseconds) how old objects in the System.ScheduledEventInformation table have to be before they are removed from the database. See [Scheduled Events - Legacy](/refguide9/scheduled-events-legacy/#cleanup) for more details. | 365 days for projects migrated from Mendix 9 and 7 days for new projects or projects with an empty database. | diff --git a/content/en/docs/refguide/runtime/runtime-server.md b/content/en/docs/refguide/runtime/runtime-server.md index 0e2ec72dd3f..0ca013160d3 100644 --- a/content/en/docs/refguide/runtime/runtime-server.md +++ b/content/en/docs/refguide/runtime/runtime-server.md @@ -49,7 +49,7 @@ This is the storage location for data files used by the app. More specifically, Database Synchronization is initiated when an app is started. It manages changes to the database structure which must be applied when you deploy an app after updating the domain model. For example, if a user adds a new attribute to an entity, the database structure must be updated to support this. -If there is more than one instance of the Runtime Server, this activity is carried out by the cluster leader. While this activity takes place, all other instances pause until the database synchronization is complete. +If there is more than one instance of the Runtime Server, this activity is coordinated across the cluster. Depending on how the Runtime is started, either the cluster leader performs the synchronization while the other instances pause until it is complete, or the instances use a database lock to agree on which instance performs it. For details, see [Cluster Leader and Cluster Followers](/refguide/clustered-mendix-runtime/#cluster-leader-follower). ### External Service Calls diff --git a/content/en/docs/refguide10/runtime/_index.md b/content/en/docs/refguide10/runtime/_index.md index 8707a3bf712..a2a276a6415 100644 --- a/content/en/docs/refguide10/runtime/_index.md +++ b/content/en/docs/refguide10/runtime/_index.md @@ -31,16 +31,7 @@ The user interacts with the Mendix Client, which then makes requests, via the [r Passing state from the Runtime Server to the Mendix Client enables the Runtime Server to be stateless, which means that any Runtime Server instance can respond to a request from the Mendix Client. A load balancer decides which Runtime Server instance will respond to a request. When a user session ends, the Runtime Server removes references to that session. -If there is more than one instance of an app, one of the instances is the *Cluster Leader*. This is responsible for Performing database synchronization tasks. It also schedules a number of cluster management activities which can then be picked up by any node. These include: - -* Session cleanup handling -* Cluster node expiration handling -* Background job expiration handling -* Unblocking blocked users -* Executing scheduled events -* Clearing persistent sessions after a new deploy - -More information on multiple instances is in [Clustered Mendix Runtime](/refguide10/clustered-mendix-runtime/). +If there is more than one instance of an app, some cluster management activities, such as database synchronization, are coordinated across the instances. For details, see [Clustered Mendix Runtime](/refguide10/clustered-mendix-runtime/#cluster-leader-follower). ### External Services diff --git a/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md b/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md index a2b984f970c..841f1ad8a66 100644 --- a/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md +++ b/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md @@ -27,27 +27,29 @@ This means that a Mendix cluster requires a load balancer to distribute the load ## Cluster Leader and Cluster Followers{#cluster-leader-follower} -Mendix Runtime has the concept of a cluster leader. This is a single node within a Mendix Runtime cluster that performs the initial database synchronization with Domain Model changes and initiates other cluster management activities which can be be picked by any node in a multi-node environment. These are the activities: +How database synchronization is coordinated across cluster nodes depends on how Mendix Runtime is started: -* **Session cleanup handling** – each node expires its sessions (meaning, not being used for a configured timespan) and the cluster leader removes the sessions persisted in the database - * In exceptional cases (for example, a node crash), some sessions may not be removed from the database, in which case the cluster leader makes sure this removal still happens -* **Cluster node expiration handling** – removing cluster nodes after they have expired (meaning, not giving a heartbeat for a configured timespan) -* **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan) -* **Unblocking blocked users** -* **Cleanup unreferenced files** - removing from storage any file documents that have been deleted, replaced, or were never committed -* **Executing Scheduled Events** – legacy scheduled events are only executed on the cluster leader; task queue based scheduled events are executed on an arbitrary cluster node -* **Performing database synchronization after new deploy** -* **Clear persistent sessions after new deploy** – invalidating all existing sessions so that they get in sync with the latest model version +* **Leader-based startup** – Used when the Runtime is started through the administrative API. This is how most managed deployments, including the Cloud Foundry buildpack, SAP BTP, and an on-premises installation managed with the Mendix Service Console, start the app. In this model, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader performs the initial database synchronization with Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. Which node is the cluster leader is controlled with the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide10/custom-settings/#commendixcoreisClusterSlave)). +* **Leaderless startup** – Used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect in this model and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below. -The Cloud Foundry Buildpack determines which cluster node becomes the cluster leader and which become cluster followers. +{{% alert color="info" %}} +If you deploy manually using the Mendix Service Console (or another on-premises installation managed through the administrative API), you are responsible for configuring the cluster leader yourself: set `com.mendix.core.isClusterSlave` to `true` on every node except one. This setting does not apply to [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/): it is always started from a configuration file, so it always uses the leaderless startup model, and `isClusterSlave` has no effect there. +{{% /alert %}} + +Besides the startup activities described above, Mendix Runtime nodes also perform the following recurring cluster management activities. These run independently of the leader-based or leaderless startup model, and are not tied to a single designated node: -## Cluster Startup +* **Session cleanup handling** – each node expires its own sessions from its local cache (meaning, not being used for a configured timespan); removing expired sessions from the database is handled by an arbitrary cluster node, based on when each session was last active +* **Cluster node expiration handling** – every node independently removes other cluster nodes that have expired (meaning, not giving a heartbeat for a configured timespan) +* **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan) is handled by an arbitrary cluster node +* **Unblocking blocked users** is handled by an arbitrary cluster node +* **Cleanup of unreferenced files** – each node removes its own file documents that were deleted, replaced, or never committed; cleaning up files left behind by a crashed node is handled by an arbitrary cluster node +* **Executing Scheduled Events** – scheduled events are executed by an arbitrary cluster node; for details, see [Task Queue](/refguide10/task-queue/) -Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app the whole cluster is restarted and the cluster leader determines whether database synchronization is required. This means that there will be some downtime when the app is deployed while this is done. +## Cluster Startup {#cluster-startup} -If database synchronization is required, all the cluster followers will wait until the cluster leader finishes the database synchronization. When the database synchronization has finished, all the cluster nodes will become fully functional. +Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app, the whole cluster is restarted, and the database may need to be synchronized with the updated Domain Model, as described in [Cluster Leader and Cluster Followers](#cluster-leader-follower) above. This means that there might be some downtime while this is done. -If no database synchronization is required, all the cluster nodes will become fully functional directly after startup. +Once database synchronization has finished, all the cluster nodes become fully functional. If no database synchronization is required, all the cluster nodes become fully functional directly after startup. ## File Storage {#file-storage} @@ -67,10 +69,14 @@ While running a multi-node cluster, you cannot predict the node on which a micro ### Cluster-Wide Locking (Guaranteed Single Execution) -Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single node Mendix Runtime, this could be guaranteed by using JVM locks. However, in a distributed scenario, those JVMs run on different machines, so there is no locking system available. Mendix does not support cluster-wide locking, either. If this cannot be circumvented, you might need to resort to an external distributed lock manager. However, keep in mind that locking in a distributed system is complex and prone to failure (for example, via lock starvation or lock expiration.). +Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single-node Mendix Runtime, this can be guaranteed with a JVM-local lock, but a JVM-local lock cannot coordinate across the separate JVMs that make up a cluster. + +If the activity can be modeled as a microflow or Java action, you can guarantee it runs on only one node at a time by using a [Task Queue](/refguide10/task-queue/) with a cluster-wide scope and a single thread; see [Limitations](/refguide10/task-queue/#limitations) in *Task Queue*. Keep in mind that this is an at-least-once guarantee rather than a strict exactly-once guarantee: if the node running the task fails, another node picks it up and reruns it, so the activity should be idempotent. For details, see [Behavior If App Stops Unexpectedly](/refguide10/task-queue/#behavior-if-app-stops-unexpectedly) in *Task Queue*. + +For other cases, for example holding a lock for an arbitrary duration around work that cannot be modeled as a queued task, Mendix Runtime does not provide a cluster-wide locking mechanism; you need to use an external distributed lock manager. Keep in mind that locking in a distributed system is complex and prone to failure (for example, through lock starvation or lock expiration). {{% alert color="info" %}} -For the reason described above, the **Disallow concurrent execution** property of a microflow only applies to a single node. +The **Disallow** property in the [Concurrent Execution Section](/refguide10/microflow/#concurrent) of a microflow is implemented as a JVM-local lock. It prevents the microflow from being executed more than once at the same time on a single node, but it does not prevent the same microflow from running concurrently on different nodes of a cluster. To guarantee single execution across the cluster, use a cluster-wide Task Queue instead, as described above. {{% /alert %}} ## Dirty State in a Cluster diff --git a/content/en/docs/refguide10/runtime/custom-settings/_index.md b/content/en/docs/refguide10/runtime/custom-settings/_index.md index 96ce4bae988..ff617391b8f 100644 --- a/content/en/docs/refguide10/runtime/custom-settings/_index.md +++ b/content/en/docs/refguide10/runtime/custom-settings/_index.md @@ -45,7 +45,7 @@ The following custom settings can be configured: | ClientCertificateUsages | Only use this when you have multiple client certificates and you want to configure specific certificates for specific servers.
This setting defines which service must use which client certificate. See **NoClientCertificateUsages** if you want to make sure that no client certificate is used for a certain host or web service. The value of **ClientCertificateUsages** must be a comma-separated list of key/value items. A key/value item must be specified as `"identifier": "path to certificate"`.
For web services, use the imported web service name as the identifier.
For REST services, use the host name of the remote server as the identifier.
Please note that any backslash in the path must be doubled. The whole value must be enclosed by braces (`{ }`). For example: {{< figure src="/attachments/refguide10/runtime/custom-settings/code_snippet.png" class="no-border" >}} | | | NoClientCertificateUsages | Comma-separated list of host names or imported web service names that should never be contacted using a client certificate. | | | ClusterManagerActionInterval | The interval (in milliseconds) used for performing all cluster manager actions. These actions include, unblocking users, and removing invalid sessions. If nothing is specified the interval is half the `SessionTimeout`. | 300000 (5 minutes) | -| com.mendix.core.isClusterSlave | Set to `true` in a high-availability scenario when this is *not* the [Cluster Leader](/refguide10/clustered-mendix-runtime/#cluster-leader-follower). The buildpack will usually enforce this setting, but it may need to be set for some on-premises deployments. | `false` | +| com.mendix.core.isClusterSlave | Set to `true` on every node except the [Cluster Leader](/refguide10/clustered-mendix-runtime/#cluster-leader-follower) in a high-availability scenario. This setting only applies when the Runtime is started through the administrative API (the leader-based startup model); it has no effect when the Runtime is started directly from a configuration file (the leaderless startup model), which is always the case for [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/). See [Cluster Leader and Cluster Followers](/refguide10/clustered-mendix-runtime/#cluster-leader-follower) for details on both models.
{{% alert color="info" %}}Managed platforms, such as the Cloud Foundry buildpack, usually set this for you. For a manual, on-premises installation managed through the administrative API (for example, using the Mendix Service Console), you need to set this yourself on all nodes except one.{{% /alert %}} | `false` | | com.mendix.core.LenientDateTimeParsing | When set to `true`, the `parseDateTime` function will use more lenient parsing, as it did in Mendix 9. For example `parseDateTime("yyyyMMdd", "2021-11-10")` will return `2020-11-01` as a date if this is set to true, which is probably not the intended result.. If set to `false`, which is the default, this example will throw an error as it is expecting `20211110`. It is recommended to not enable this setting to avoid unexpected results. | `false` | | com.mendix.core.SameSiteCookies | The [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) property can be included in all cookies that are returned by the embedded HTTP server. The possible values are `Strict`, `Lax`, and `None`. The default is `Strict`. Setting it to `None` is typically needed only when an application is embedded in an iframe of another application with a different domain. Newer browsers may require the connection to be secure (HTTPS) when set to `None`. If the connection is plain HTTP, then this setting must be changed to `Strict` (recommended) or `Lax`. | | | com.mendix.core.ScheduledEventsCleanupAge | This setting specifies (in milliseconds) how old objects in the System.ScheduledEventInformation table have to be before they are removed from the database. See [Scheduled Events - Legacy](/refguide9/scheduled-events-legacy/#cleanup) for more details. | 365 days for projects migrated from Mendix 9 and 7 days for new projects or projects with an empty database. | diff --git a/content/en/docs/refguide10/runtime/runtime-server.md b/content/en/docs/refguide10/runtime/runtime-server.md index 15674b26eb7..6dae5b77721 100644 --- a/content/en/docs/refguide10/runtime/runtime-server.md +++ b/content/en/docs/refguide10/runtime/runtime-server.md @@ -49,7 +49,7 @@ This is the storage location for data files used by the app. More specifically, Database Synchronization is initiated when an app is started. It manages changes to the database structure which must be applied when you deploy an app after updating the domain model. For example, if a user adds a new attribute to an entity, the database structure must be updated to support this. -If there is more than one instance of the Runtime Server, this activity is carried out by the cluster leader. While this activity takes place, all other instances pause until the database synchronization is complete. +If there is more than one instance of the Runtime Server, this activity is coordinated across the cluster. Depending on how the Runtime is started, either the cluster leader performs the synchronization while the other instances pause until it is complete, or the instances use a database lock to agree on which instance performs it. For details, see [Cluster Leader and Cluster Followers](/refguide10/clustered-mendix-runtime/#cluster-leader-follower). ### External Service Calls From c784fa99f1097c5e544f9987b9c091e868e75b24 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Fri, 30 Oct 2026 13:41:00 +0100 Subject: [PATCH 2/4] Proofread --- .../microflows/microflow.md | 6 +++++ .../runtime/clustered-mendix-runtime.md | 23 +++++++++++-------- .../docs/refguide/runtime/runtime-server.md | 2 +- .../runtime/clustered-mendix-runtime.md | 2 +- .../docs/refguide10/runtime/runtime-server.md | 2 +- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md b/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md index 59dab89f2f0..2a26521d2bc 100644 --- a/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md +++ b/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md @@ -6,6 +6,8 @@ weight: 1 ## Introduction +{{% todo %}}Copy changes to Mx10{{% /todo %}} + This document describes the properties of a microflow. If you want to see what microflows are for and what kind of elements they contain, you can check [Microflows](/refguide/microflows/). If you want to know about the settings of the **Call a microflow** event action, you can check [Microflow Settings](/refguide/on-click-event/#microflow-settings). ## Properties @@ -131,6 +133,10 @@ Disallowing concurrent execution of a microflow can be useful if a microflow wou | Disabled *(default)* | It is possible to execute the microflow more than once concurrently. | | Enabled | It is not possible to execute the microflow more than once concurrently; the user receives a message or another microflow is executed instead. | +{{% alert color="info" %}} +This property relates to microflows running on a single node in a clustered environment. See [Cluster-Wide Locking](/refguide/clustered-mendix-runtime/#cluster-lock) in *Clustered Mendix Runtime* for more information. +{{% /alert %}} + #### Error Message **Error message** defines the message the user gets when concurrent execution is not allowed and the user tries to start the microflow while it is already being executed. This will not be shown if there is an **Error microflow** defined. diff --git a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md index 40d30d85ec5..44d4c78c306 100644 --- a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md +++ b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md @@ -7,6 +7,8 @@ description: "Describes the cluster functionality of the Mendix Runtime, which a ## Introduction +{{% todo %}}Copy changes to Mx10{{% /todo %}} + This page describes the behavior and impact of running Mendix Runtime as a cluster. Using the cluster functionality, you can set up your Mendix application to run behind a load balancer to enable a failover and/or high availability architecture. The main feature enabling clustering is Mendix's stateless runtime architecture. This means that the dirty state (the non-persistable entity instances and not-yet-persisted changes) are stored on the client and not on the server. This enables much easier scaling of the Mendix Runtime, as each cluster node can handle any request from the client. The stateless runtime architecture also allows for better dirty state maintainability and better insight in application state. @@ -27,14 +29,15 @@ This means that a Mendix cluster requires a load balancer to distribute the load ## Cluster Leader and Cluster Followers{#cluster-leader-follower} -How database synchronization is coordinated across cluster nodes depends on how Mendix Runtime is started: +Database synchronization is coordinated across cluster nodes depending on how Mendix Runtime is started: -* **Leader-based startup** – Used when the Runtime is started through the administrative API. This is how most managed deployments, including the Cloud Foundry buildpack, SAP BTP, and an on-premises installation managed with the Mendix Service Console, start the app. In this model, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader performs the initial database synchronization with Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. Which node is the cluster leader is controlled with the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide/custom-settings/#commendixcoreisClusterSlave)). -* **Leaderless startup** – Used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect in this model and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below. +* **Leader-based startup** – This is used when the Runtime is started through the administrative API. This is how most managed deployments start the app: for example, the Cloud Foundry buildpack, SAP BTP, or an on-premises installation managed with the Mendix Service Console. With this mechanism, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader initially synchronizes the database with any Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. The cluster leader node is controlled by the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide/custom-settings/#commendixcoreisClusterSlave)). -{{% alert color="info" %}} -If you deploy manually using the Mendix Service Console (or another on-premises installation managed through the administrative API), you are responsible for configuring the cluster leader yourself: set `com.mendix.core.isClusterSlave` to `true` on every node except one. This setting does not apply to [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/): it is always started from a configuration file, so it always uses the leaderless startup model, and `isClusterSlave` has no effect there. -{{% /alert %}} + {{% alert color="info" %}}If you deploy manually using the Mendix Service Console (or another on-premises installation managed through the administrative API), you are responsible for configuring the cluster leader yourself by setting `com.mendix.core.isClusterSlave` to `true` on every node except one.{{% /alert %}} + +* **Leaderless startup** – This is used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect when using this mechanism and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below. + +## Other Cluster Management Activities Besides the startup activities described above, Mendix Runtime nodes also perform the following recurring cluster management activities. These run independently of the leader-based or leaderless startup model, and are not tied to a single designated node: @@ -67,13 +70,13 @@ It is possible to configure `After-Startup` and `Before-Shutdown` microflows in While running a multi-node cluster, you cannot predict the node on which a microflow will be executed. Therefore, it is not possible to debug such a microflow execution in a cluster from Mendix Studio Pro. However, you can still debug a microflow while running a single instance of the Mendix Runtime. -### Cluster-Wide Locking (Guaranteed Single Execution) +### Cluster-Wide Locking (Guaranteed Single Execution){#cluster-lock} -Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single-node Mendix Runtime, this can be guaranteed with a JVM-local lock, but a JVM-local lock cannot coordinate across the separate JVMs that make up a cluster. +Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single-node Mendix Runtime, this can be guaranteed with a lock which is local to a Java virtual machine (a JVM-local lock). In a cluster, you cannot set a JVM-local lock across the separate JVMs that make up the cluster. -If the activity can be modeled as a microflow or Java action, you can guarantee it runs on only one node at a time by using a [Task Queue](/refguide/task-queue/) with a cluster-wide scope and a single thread; see [Limitations](/refguide/task-queue/#limitations) in *Task Queue*. Keep in mind that this is an at-least-once guarantee rather than a strict exactly-once guarantee: if the node running the task fails, another node picks it up and reruns it, so the activity should be idempotent. For details, see [Behavior If App Stops Unexpectedly](/refguide/task-queue/#behavior-if-app-stops-unexpectedly) in *Task Queue*. +If the activity can be modeled as a microflow or Java action, you can use a [Task Queue](/refguide/task-queue/) with a cluster-wide scope and a single thread to guarantee it runs on only one node at a time (see [Limitations](/refguide/task-queue/#limitations) in *Task Queue*). Keep in mind that this is an at-least-once guarantee rather than a strict exactly-once guarantee: if the node running the task fails, another node picks it up and reruns it, so the activity must be idempotent (safe to run multiple times with the same parameters). For details, see [Behavior If App Stops Unexpectedly](/refguide/task-queue/#behavior-if-app-stops-unexpectedly) in *Task Queue*. -For other cases, for example holding a lock for an arbitrary duration around work that cannot be modeled as a queued task, Mendix Runtime does not provide a cluster-wide locking mechanism; you need to use an external distributed lock manager. Keep in mind that locking in a distributed system is complex and prone to failure (for example, through lock starvation or lock expiration). +Mendix Runtime does not provide a cluster-wide locking mechanism for other cases, for example holding a lock for an arbitrary duration around work that cannot be modeled as a queued task. In these cases, you need to use an external distributed lock manager. Keep in mind that locking in a distributed system is complex and prone to failure (for example, through lock starvation or lock expiration). {{% alert color="info" %}} The **Disallow** property in the [Concurrent Execution Section](/refguide/microflow/#concurrent) of a microflow is implemented as a JVM-local lock. It prevents the microflow from being executed more than once at the same time on a single node, but it does not prevent the same microflow from running concurrently on different nodes of a cluster. To guarantee single execution across the cluster, use a cluster-wide Task Queue instead, as described above. diff --git a/content/en/docs/refguide/runtime/runtime-server.md b/content/en/docs/refguide/runtime/runtime-server.md index 0ca013160d3..b0d390ea9af 100644 --- a/content/en/docs/refguide/runtime/runtime-server.md +++ b/content/en/docs/refguide/runtime/runtime-server.md @@ -49,7 +49,7 @@ This is the storage location for data files used by the app. More specifically, Database Synchronization is initiated when an app is started. It manages changes to the database structure which must be applied when you deploy an app after updating the domain model. For example, if a user adds a new attribute to an entity, the database structure must be updated to support this. -If there is more than one instance of the Runtime Server, this activity is coordinated across the cluster. Depending on how the Runtime is started, either the cluster leader performs the synchronization while the other instances pause until it is complete, or the instances use a database lock to agree on which instance performs it. For details, see [Cluster Leader and Cluster Followers](/refguide/clustered-mendix-runtime/#cluster-leader-follower). +If there is more than one instance of the Runtime Server, this activity is coordinated across the cluster. Depending on how the Runtime is started, either the cluster leader performs the synchronization while the other instances pause until it is complete, or the instances use a database lock to agree on which instance performs it. For details, see [Cluster Leader and Cluster Followers](/refguide/clustered-mendix-runtime/#cluster-leader-follower) in *Clustered Mendix Runtime*. ### External Service Calls diff --git a/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md b/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md index 841f1ad8a66..8ece31dbf06 100644 --- a/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md +++ b/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md @@ -27,7 +27,7 @@ This means that a Mendix cluster requires a load balancer to distribute the load ## Cluster Leader and Cluster Followers{#cluster-leader-follower} -How database synchronization is coordinated across cluster nodes depends on how Mendix Runtime is started: +Database synchronization is coordinated across cluster nodes depending on how Mendix Runtime is started: * **Leader-based startup** – Used when the Runtime is started through the administrative API. This is how most managed deployments, including the Cloud Foundry buildpack, SAP BTP, and an on-premises installation managed with the Mendix Service Console, start the app. In this model, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader performs the initial database synchronization with Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. Which node is the cluster leader is controlled with the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide10/custom-settings/#commendixcoreisClusterSlave)). * **Leaderless startup** – Used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect in this model and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below. diff --git a/content/en/docs/refguide10/runtime/runtime-server.md b/content/en/docs/refguide10/runtime/runtime-server.md index 6dae5b77721..6c5edbfc016 100644 --- a/content/en/docs/refguide10/runtime/runtime-server.md +++ b/content/en/docs/refguide10/runtime/runtime-server.md @@ -49,7 +49,7 @@ This is the storage location for data files used by the app. More specifically, Database Synchronization is initiated when an app is started. It manages changes to the database structure which must be applied when you deploy an app after updating the domain model. For example, if a user adds a new attribute to an entity, the database structure must be updated to support this. -If there is more than one instance of the Runtime Server, this activity is coordinated across the cluster. Depending on how the Runtime is started, either the cluster leader performs the synchronization while the other instances pause until it is complete, or the instances use a database lock to agree on which instance performs it. For details, see [Cluster Leader and Cluster Followers](/refguide10/clustered-mendix-runtime/#cluster-leader-follower). +If there is more than one instance of the Runtime Server, this activity is coordinated across the cluster. Depending on how the Runtime is started, either the cluster leader performs the synchronization while the other instances pause until it is complete, or the instances use a database lock to agree on which instance performs it. For details, see [Cluster Leader and Cluster Followers](/refguide10/clustered-mendix-runtime/#cluster-leader-follower) in *Clustered Mendix Runtime*. ### External Service Calls From 0b07734dff034141d95f169de226f0e6d5f8cc41 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Fri, 30 Oct 2026 15:59:54 +0100 Subject: [PATCH 3/4] Respond to final review --- content/en/docs/refguide/runtime/clustered-mendix-runtime.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md index 44d4c78c306..59ab1c216ff 100644 --- a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md +++ b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md @@ -41,7 +41,7 @@ Database synchronization is coordinated across cluster nodes depending on how Me Besides the startup activities described above, Mendix Runtime nodes also perform the following recurring cluster management activities. These run independently of the leader-based or leaderless startup model, and are not tied to a single designated node: -* **Session cleanup handling** – each node expires its own sessions from its local cache (meaning, not being used for a configured timespan); removing expired sessions from the database is handled by an arbitrary cluster node, based on when each session was last active +* **Session cleanup handling** – removing expired sessions from the database is handled by an arbitrary cluster node * **Cluster node expiration handling** – every node independently removes other cluster nodes that have expired (meaning, not giving a heartbeat for a configured timespan) * **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan) is handled by an arbitrary cluster node * **Unblocking blocked users** is handled by an arbitrary cluster node @@ -50,7 +50,7 @@ Besides the startup activities described above, Mendix Runtime nodes also perfor ## Cluster Startup {#cluster-startup} -Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app, the whole cluster is restarted, and the database may need to be synchronized with the updated Domain Model, as described in [Cluster Leader and Cluster Followers](#cluster-leader-follower) above. This means that there might be some downtime while this is done. +Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app the whole cluster should be restarted, and the database may need to be synchronized with the updated Domain Model, as described in [Cluster Leader and Cluster Followers](#cluster-leader-follower), above. Once database synchronization has finished, all the cluster nodes become fully functional. If no database synchronization is required, all the cluster nodes become fully functional directly after startup. From 09603a49bebb0d64f5fc5d060accbc011ffe29a5 Mon Sep 17 00:00:00 2001 From: MarkvanMents Date: Fri, 30 Oct 2026 16:34:29 +0100 Subject: [PATCH 4/4] Copy changes to refguide10 documentation --- .../microflows/microflow.md | 2 -- .../runtime/clustered-mendix-runtime.md | 2 -- .../microflows/microflow.md | 4 ++++ .../runtime/clustered-mendix-runtime.md | 23 ++++++++++--------- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md b/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md index 2a26521d2bc..e5c74ce9e17 100644 --- a/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md +++ b/content/en/docs/refguide/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md @@ -6,8 +6,6 @@ weight: 1 ## Introduction -{{% todo %}}Copy changes to Mx10{{% /todo %}} - This document describes the properties of a microflow. If you want to see what microflows are for and what kind of elements they contain, you can check [Microflows](/refguide/microflows/). If you want to know about the settings of the **Call a microflow** event action, you can check [Microflow Settings](/refguide/on-click-event/#microflow-settings). ## Properties diff --git a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md index 59ab1c216ff..0b8e130166d 100644 --- a/content/en/docs/refguide/runtime/clustered-mendix-runtime.md +++ b/content/en/docs/refguide/runtime/clustered-mendix-runtime.md @@ -7,8 +7,6 @@ description: "Describes the cluster functionality of the Mendix Runtime, which a ## Introduction -{{% todo %}}Copy changes to Mx10{{% /todo %}} - This page describes the behavior and impact of running Mendix Runtime as a cluster. Using the cluster functionality, you can set up your Mendix application to run behind a load balancer to enable a failover and/or high availability architecture. The main feature enabling clustering is Mendix's stateless runtime architecture. This means that the dirty state (the non-persistable entity instances and not-yet-persisted changes) are stored on the client and not on the server. This enables much easier scaling of the Mendix Runtime, as each cluster node can handle any request from the client. The stateless runtime architecture also allows for better dirty state maintainability and better insight in application state. diff --git a/content/en/docs/refguide10/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md b/content/en/docs/refguide10/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md index ec9b7b21577..9216f834611 100644 --- a/content/en/docs/refguide10/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md +++ b/content/en/docs/refguide10/modeling/application-logic/microflows-and-nanoflows/microflows/microflow.md @@ -127,6 +127,10 @@ Disallowing concurrent execution of a microflow can be useful if a microflow wou | Disabled *(default)* | It is possible to execute the microflow more than once concurrently. | | Enabled | It is not possible to execute the microflow more than once concurrently; the user receives a message or another microflow is executed instead. | +{{% alert color="info" %}} +This property relates to microflows running on a single node in a clustered environment. See [Cluster-Wide Locking](/refguide10/clustered-mendix-runtime/#cluster-lock) in *Clustered Mendix Runtime* for more information. +{{% /alert %}} + #### Error Message **Error message** defines the message the user gets when concurrent execution is not allowed and the user tries to start the microflow while it is already being executed. This will not be shown if there is an **Error microflow** defined. diff --git a/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md b/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md index 8ece31dbf06..7ccf7900e58 100644 --- a/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md +++ b/content/en/docs/refguide10/runtime/clustered-mendix-runtime.md @@ -29,16 +29,17 @@ This means that a Mendix cluster requires a load balancer to distribute the load Database synchronization is coordinated across cluster nodes depending on how Mendix Runtime is started: -* **Leader-based startup** – Used when the Runtime is started through the administrative API. This is how most managed deployments, including the Cloud Foundry buildpack, SAP BTP, and an on-premises installation managed with the Mendix Service Console, start the app. In this model, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader performs the initial database synchronization with Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. Which node is the cluster leader is controlled with the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide10/custom-settings/#commendixcoreisClusterSlave)). -* **Leaderless startup** – Used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect in this model and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below. +* **Leader-based startup** – This is used when the Runtime is started through the administrative API. This is how most managed deployments start the app: for example, the Cloud Foundry buildpack, SAP BTP, or an on-premises installation managed with the Mendix Service Console. With this mechanism, exactly one node is the *cluster leader* and the other nodes are *cluster followers*. The cluster leader initially synchronizes the database with any Domain Model changes and clears persistent sessions after a new deploy; see [Cluster Startup](#cluster-startup) below. The cluster leader node is controlled by the `com.mendix.core.isClusterSlave` custom setting (see [Runtime Customization](/refguide10/custom-settings/#commendixcoreisClusterSlave)). -{{% alert color="info" %}} -If you deploy manually using the Mendix Service Console (or another on-premises installation managed through the administrative API), you are responsible for configuring the cluster leader yourself: set `com.mendix.core.isClusterSlave` to `true` on every node except one. This setting does not apply to [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/): it is always started from a configuration file, so it always uses the leaderless startup model, and `isClusterSlave` has no effect there. -{{% /alert %}} + {{% alert color="info" %}}If you deploy manually using the Mendix Service Console (or another on-premises installation managed through the administrative API), you are responsible for configuring the cluster leader yourself by setting `com.mendix.core.isClusterSlave` to `true` on every node except one.{{% /alert %}} + +* **Leaderless startup** – This is used when the Runtime is started directly from a configuration file instead of through the administrative API. [Mendix Portable Runtime](/developerportal/deploy/portable-app-distribution-deploy/) (previously called Portable App Distribution, or PAD) always runs this way: its start script always launches the Runtime with a configuration file. In this model, there is no cluster leader. Database synchronization is coordinated using a database lock: whichever node acquires the lock performs the synchronization while the other nodes wait. The `com.mendix.core.isClusterSlave` setting has no effect when using this mechanism and is ignored. Persistent sessions are not explicitly cleared as a separate deploy step in this model; they are left to expire normally, as described in [Sessions Are Always Persistent](#sessions-are-always-persistent) below. + +## Other Cluster Management Activities Besides the startup activities described above, Mendix Runtime nodes also perform the following recurring cluster management activities. These run independently of the leader-based or leaderless startup model, and are not tied to a single designated node: -* **Session cleanup handling** – each node expires its own sessions from its local cache (meaning, not being used for a configured timespan); removing expired sessions from the database is handled by an arbitrary cluster node, based on when each session was last active +* **Session cleanup handling** – removing expired sessions from the database is handled by an arbitrary cluster node * **Cluster node expiration handling** – every node independently removes other cluster nodes that have expired (meaning, not giving a heartbeat for a configured timespan) * **Background job expiration handling** – removing data about background jobs after the information has expired (meaning, older than a specific timespan) is handled by an arbitrary cluster node * **Unblocking blocked users** is handled by an arbitrary cluster node @@ -47,7 +48,7 @@ Besides the startup activities described above, Mendix Runtime nodes also perfor ## Cluster Startup {#cluster-startup} -Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app, the whole cluster is restarted, and the database may need to be synchronized with the updated Domain Model, as described in [Cluster Leader and Cluster Followers](#cluster-leader-follower) above. This means that there might be some downtime while this is done. +Individual nodes in a cluster can be started and stopped with no impact on the uptime of the app. However, when you deploy a new version of the app the whole cluster should be restarted, and the database may need to be synchronized with the updated Domain Model, as described in [Cluster Leader and Cluster Followers](#cluster-leader-follower), above. Once database synchronization has finished, all the cluster nodes become fully functional. If no database synchronization is required, all the cluster nodes become fully functional directly after startup. @@ -67,13 +68,13 @@ It is possible to configure `After-Startup` and `Before-Shutdown` microflows in While running a multi-node cluster, you cannot predict the node on which a microflow will be executed. Therefore, it is not possible to debug such a microflow execution in a cluster from Mendix Studio Pro. However, you can still debug a microflow while running a single instance of the Mendix Runtime. -### Cluster-Wide Locking (Guaranteed Single Execution) +### Cluster-Wide Locking (Guaranteed Single Execution){#cluster-lock} -Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single-node Mendix Runtime, this can be guaranteed with a JVM-local lock, but a JVM-local lock cannot coordinate across the separate JVMs that make up a cluster. +Some apps require a guaranteed single execution of a certain activity at a given point in time. In a single-node Mendix Runtime, this can be guaranteed with a lock which is local to a Java virtual machine (a JVM-local lock). In a cluster, you cannot set a JVM-local lock across the separate JVMs that make up the cluster. -If the activity can be modeled as a microflow or Java action, you can guarantee it runs on only one node at a time by using a [Task Queue](/refguide10/task-queue/) with a cluster-wide scope and a single thread; see [Limitations](/refguide10/task-queue/#limitations) in *Task Queue*. Keep in mind that this is an at-least-once guarantee rather than a strict exactly-once guarantee: if the node running the task fails, another node picks it up and reruns it, so the activity should be idempotent. For details, see [Behavior If App Stops Unexpectedly](/refguide10/task-queue/#behavior-if-app-stops-unexpectedly) in *Task Queue*. +If the activity can be modeled as a microflow or Java action, you can use a [Task Queue](/refguide10/task-queue/) with a cluster-wide scope and a single thread to guarantee it runs on only one node at a time (see [Limitations](/refguide10/task-queue/#limitations) in *Task Queue*). Keep in mind that this is an at-least-once guarantee rather than a strict exactly-once guarantee: if the node running the task fails, another node picks it up and reruns it, so the activity must be idempotent (safe to run multiple times with the same parameters). For details, see [Behavior If App Stops Unexpectedly](/refguide10/task-queue/#behavior-if-app-stops-unexpectedly) in *Task Queue*. -For other cases, for example holding a lock for an arbitrary duration around work that cannot be modeled as a queued task, Mendix Runtime does not provide a cluster-wide locking mechanism; you need to use an external distributed lock manager. Keep in mind that locking in a distributed system is complex and prone to failure (for example, through lock starvation or lock expiration). +Mendix Runtime does not provide a cluster-wide locking mechanism for other cases, for example holding a lock for an arbitrary duration around work that cannot be modeled as a queued task. In these cases, you need to use an external distributed lock manager. Keep in mind that locking in a distributed system is complex and prone to failure (for example, through lock starvation or lock expiration). {{% alert color="info" %}} The **Disallow** property in the [Concurrent Execution Section](/refguide10/microflow/#concurrent) of a microflow is implemented as a JVM-local lock. It prevents the microflow from being executed more than once at the same time on a single node, but it does not prevent the same microflow from running concurrently on different nodes of a cluster. To guarantee single execution across the cluster, use a cluster-wide Task Queue instead, as described above.