Store Swiftlet (HA)
Overview
The High Availability (HA) Store Swiftlet extends the standard CE Store Swiftlet by adding synchronous replication of all persistent data between an ACTIVE and a STANDBY instance for failover scenarios. All store operations are synchronously mirrored to the STANDBY, ensuring no data loss during failover. For standard store features such as swap files, backup, shrink, and cache management, refer to the CE Store Swiftlet documentation.
Features
Synchronous Store Replication
In HA mode, the Store Swiftlet replicates all persistent data changes (database, transaction log, and durable subscriber files) from the ACTIVE to the STANDBY instance using a dedicated replication protocol. Every store operation (such as page creation, update, deletion, and transaction log writes) is transmitted to the STANDBY and only acknowledged to the application once the STANDBY has successfully received and applied the change. This ensures that the STANDBY is always in a consistent state and ready for immediate takeover in case of failover.
Replication is performed at the protocol level using a set of request types (e.g., PageDBPutRequest, TxLogWriteRequest, DurableDeleteRequest) that mirror all store mutations. The ACTIVE instance acts as a replication source, while the STANDBY acts as a sink and applies all received requests to its local store files.
Transaction Log Replication
All transaction log writes are synchronously sent from the ACTIVE to the STANDBY. The transaction log is kept in memory on the ACTIVE while in HA mode for performance, and is flushed to disk only when switching to standalone mode or during a controlled shutdown. The STANDBY receives transaction log chunks and reconstructs the log file locally, ensuring transactional consistency.
Store Image Transfer
When a STANDBY instance joins or resumes, the ACTIVE sends a full image of the current store files (database, transaction log, and durable subscriber files) to the STANDBY. This is done using file chunk requests to efficiently transfer large files in segments. The STANDBY deletes any old content before applying the new image, and can optionally back up previous files in split-brain scenarios.
Durable Subscriber Replication
All changes to durable subscriber state (creation, update, deletion) are mirrored to the STANDBY. Durable subscriber files are transferred in full when created or updated, and deleted on the STANDBY when removed on the ACTIVE.
HA Store Modes and Store Types
The HA Store Swiftlet supports three persistent store deployment options, each with different trade-offs for performance, reliability, and operational complexity:
-
Replicated File Store: Each HA node maintains its own local store files. All changes are synchronously replicated over the network. This is the default and recommended mode for most deployments, as it provides full redundancy and no single point of failure.
-
Shared File Store: Both ACTIVE and STANDBY instances access the same shared filesystem (e.g., NFS or SAN). Replication is not performed; both nodes see the same files. This mode is enabled by setting the
shared-storeproperty totrue. It reduces network replication overhead but introduces a dependency on the shared storage's availability and performance. -
Shared JDBC Store: Both nodes use the same JDBC-accessible database for persistence. This is a variant of shared store mode, and also requires
shared-storeto be set totrue.
When shared-store is enabled, the replication protocol is bypassed and both nodes directly access the same underlying store. In this case, the STANDBY does not receive replicated changes, but instead relies on the shared storage for consistency.
Replicated File Store
Default mode. Each node has its own local files. All modifications are synchronously replicated from ACTIVE to STANDBY. Provides maximum redundancy and no single point of failure.
Shared File Store
Both nodes access the same physical files via a shared filesystem. Set shared-store to true to enable. No network replication occurs. Availability depends on the shared storage.
Shared JDBC Store
Both nodes use the same JDBC database for persistence. Also requires shared-store to be true. No network replication occurs.
Configuration Example:
<swiftlet name="sys$store" shared-store="true"/>
Force Sync in Standalone Mode
The force-sync-in-standalone-mode property (under the transaction-log entity) controls whether the transaction log is forcibly synced to disk when the HA instance operates in STANDALONE mode (i.e., not participating in HA replication). By default, this is enabled (true), ensuring maximum durability when the node is running independently. When operating as ACTIVE in HA, the transaction log is kept in memory for performance, and only flushed to disk when switching to STANDALONE or during shutdown.
Configuration Example:
<swiftlet name="sys$store">
<transaction-log force-sync-in-standalone-mode="false"/>
</swiftlet>
HA State Transitions and Store Behavior
The Store Swiftlet adapts its behavior based on the HA state (ACTIVE, STANDBY, STANDALONE):
- In ACTIVE mode, all store operations are performed locally and synchronously replicated to the STANDBY. The transaction log is kept in memory for performance.
- In STANDBY mode, the instance receives and applies all replicated operations from the ACTIVE, maintaining a hot backup.
- In STANDALONE mode (when not connected to a partner), the store operates as a standard, non-replicated store, and the transaction log is always flushed to disk if
force-sync-in-standalone-modeis enabled.
Switching between modes triggers appropriate initialization, replication, and file synchronization to ensure consistency.
Configuration Guide
Enable Shared Store Mode (Shared Filesystem or JDBC)
Use this scenario when both HA nodes should access the same physical store files (either via NFS/SAN or a shared JDBC database). This disables network replication and relies on the shared storage for persistence.
- Set the
shared-storeattribute totrueon the sys$store swiftlet. - Restart both HA nodes to apply the change.
<swiftlet name="sys$store" shared-store="true"/>
Disable Force Sync in Standalone Mode
Use this scenario if you want to improve performance when running in STANDALONE mode and are willing to accept the risk of data loss in case of a crash.
- Set the
force-sync-in-standalone-modeattribute tofalseunder thetransaction-logentity. - Restart the router for the change to take effect.
<swiftlet name="sys$store">
<transaction-log force-sync-in-standalone-mode="false"/>
</swiftlet>
Configuration Reference
The top-level entity in routerconfig.xml is <swiftlet name="sys$store">.
<swiftlet name="sys$store"> Properties
These properties are attributes of the <swiftlet name="sys$store"> entity.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
shared-store |
Boolean | false |
No | Yes | Use a shared Store |
<swiftlet name="sys$store" shared-store="false"/>
<backup> Entity
Backup Settings
This is a fixed child entity of <swiftlet name="sys$store">.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
path |
String | ./ |
No | No | Root Path for Backup Save Sets |
keep-generations |
Integer | 3 |
No | No | Number of Generations to keep (min: 1) |
<swiftlet name="sys$store">
<backup path="..." keep-generations="..."/>
</swiftlet>
<database> Entity
Database Settings
This is a fixed child entity of <swiftlet name="sys$store">.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
path |
String | ./ |
No | Yes | Path of the Database (page.db) |
initial-db-size-pages |
Integer | 25600 |
No | Yes | Initial Size of the Database in Pages (min: 10) |
size-collect-interval |
Long | 1000 |
No | No | Interval to collect the Usage |
page-size-current |
Integer | 2048 |
No | No | Current Size of the Database Pages |
page-size-recommended |
Integer | 2048 |
No | No | Recommended Size of the Database Pages |
page-size-max |
Integer | 32768 |
No | No | Maximum Page Size (min: 2048) |
perform-compact-on-startup |
Boolean | false |
No | No | Perform a compact of the page.db on startup if current page size is equal to recommended page size |
perform-resize-on-startup |
Boolean | false |
No | No | Perform a page resize on startup if the recommended size is greater than the current page size |
<swiftlet name="sys$store">
<database path="..." initial-db-size-pages="..." size-collect-interval="..." page-size-current="..." page-size-recommended="..." page-size-max="..." perform-compact-on-startup="..." perform-resize-on-startup="..."/>
</swiftlet>
<cache> Entity
Cache Settings
This is a fixed child entity of <swiftlet name="sys$store">.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
min-size |
Integer | 1024 |
No | Yes | Min. Size (Pages) (min: 512) |
max-size |
Integer | 2048 |
No | Yes | Max. Size (Pages) (min: 512) |
<swiftlet name="sys$store">
<cache min-size="..." max-size="..."/>
</swiftlet>
<transaction-log> Entity
Transaction Log Settings
This is a fixed child entity of <swiftlet name="sys$store">.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
path |
String | ./ |
No | Yes | Path of the Transaction Log (transaction.log) |
checkpoint-size |
Long | 104857600 |
No | Yes | Size at which a Checkpoint is performed (min: 1048576) |
force-sync |
Boolean | false |
No | Yes | Force a sync with the disk |
force-sync-in-standalone-mode |
Boolean | true |
No | No | Force a sync with the disk while the HA instance is in STANDALONE mode |
<swiftlet name="sys$store">
<transaction-log path="..." checkpoint-size="..." force-sync="..." force-sync-in-standalone-mode="..."/>
</swiftlet>
<swap> Entity
Swap Settings
This is a fixed child entity of <swiftlet name="sys$store">.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
path |
String | ./ |
No | Yes | Path of Swap Files |
roll-over-size |
Long | 10485760 |
No | Yes | Roll Over Size (min: 1048576) |
<swiftlet name="sys$store">
<swap path="..." roll-over-size="..."/>
</swiftlet>
<durable-subscriber> Entity
Durable Subscriber Settings
This is a fixed child entity of <swiftlet name="sys$store">.
| Parameter | Type | Default | Mandatory | Reboot Required | Description |
|---|---|---|---|---|---|
path |
String | ./ |
No | Yes | Path of Durable Subscriber Files |
<swiftlet name="sys$store">
<durable-subscriber path="..."/>
</swiftlet>