Overview

SymmetricDS Pro 3.18 release includes 42 features, 108 improvements, and 112 bug fixes.

Security Fixes

Issue Summary Severity

SYM-7386

Implement Docker Hardened Images (DHI community) for SymmetricPRO (Pro)

Medium

SYM-7444

Upgrade Spring Boot to 4.0.6

Medium

SYM-7510

Minimum-privilege runtime account for container image (Pro)

High

SYM-7558

Improvements per SonarCloud security and maintainability report (Pro)

High

SYM-7610

Update min Java requirement to 21 and IzPack to version 5.2.6 (Java 9+ to run Setup jar) (Pro)

Medium

SYM-7657

Address logback licensing conflict

High

SYM-7669

Spring-Security version 7.0.6

High

SYM-7693

Add Admin console user if password is preconfigured

Medium

SYM-7830

Upgrade Spring Boot to 4.1.0 to fix Jakarta and Tomcat dependencies

High

SYM-7894

Update Spring Security to version 7.1.1

High

SYM-8115

Upgrade H2 library to 2.5.252

High

SYM-8125

Remove vulnerable tika-parsers 1.28.5 and Apache CXF 3.5.3 pulled into symmetric-pro-izpack by IzPack 5.2.6 (Pro)

Medium

SYM-8131

Upgrade FasterXML Jackson suite to version 3.2.2 (Pro)

High

SYM-8136

Authenticate outbound sync calls with JWT bearer token (Pro)

High

Performance Fixes

Issue Summary Severity

SYM-7534

Add Liveliness endpoint APIs for Kubernetes/Docker probe integration

High

SYM-7568

AS/400 multi-journal: add debug logging for per-journal SCN ranges (Pro)

Medium

SYM-7582

Use HikariCP as default value for db.pool.type

High

SYM-7634

Prioritize start of registration node when multi-homed with client nodes

Low

SYM-7732

When the Watchdog job disables a node that uses internal communication, the client side of the process never executes

High

SYM-7745

New Health Check (database performance) test dialog (Pro)

Medium

SYM-7841

Preserve original value for db.pool.type on upgrade from pre 3.18 version

Medium

SYM-7848

Database Health Tracker helps jobs and connection manager perform a preflight check of DB connection before running

Medium

SYM-7873

AS/400 faster skip of tables not configured for replication (Pro)

Medium

SYM-7900

Launch scripts in bin/ directory fail when install path contains spaces

Medium

SYM-7929

Deferred foreign keys and indexes silently dropped when an initial load uses multiple extract threads

High

SYM-7935

Log4j → Logback migration failure: logback.xml packaged in installation is confused for custom costumer configuration

Medium

SYM-7968

Built-in Metrics rows.create.time.min/max are never cleared after unrouted data reaches zero

High

SYM-7975

Test available connections on performance check prior to deploy (Pro)

High

SYM-7978

Drop sym_node_channel_ctl during upgrade of SymmetricDS from pre 3.17 versions

Medium

SYM-8065

Add monitor to alert about node group links whose target group has no members

Medium

SYM-8067

Log effective DB connection pool size at startup and warn when concurrent workers exceed it

High

SYM-8076

Optimize slow OBJECT_NAME()/OBJECTPROPERTY() from WHERE clauses of MsSqlDdlReader catalog queries (table metadata on MS SQL Server)

High

SYM-8079

Set a lock timeout to prevent blocking DDL reader metadata queries (MS SQL Server) (Pro)

High

SYM-8082

Optimize read of column metadata for tables (MS SQL Server)

High

SYM-8083

Trigger template hash is computed non-thread-safe (rebuilds more often than necessary)

High

SYM-8098

Client should expire reservation cookie when the server returns SC_SERVICE_BUSY

High

SYM-8099

Skip reservation process, when filtered list of batches to push is empty

High

SYM-8100

Abandoned Push-Reservations occupy the connection pool until timeout

High

What’s New

License Change: GNU AGPL v3

Starting with this release on September 1, 2026, Jumpmind is relicensing SymmetricDS from the GNU General Public License (GPL) v3 to the GNU Affero General Public License (AGPL) v3. For the vast majority of users, nothing changes. Commits merged after this release are licensed under AGPL v3. Projects with automated license-compliance tooling may need to update their policy rules to approve AGPL v3 for this repository.

We see this change as a positive one that will benefit our open source users, but this change may have consequences on others. If the license change affects your ability to publish a software product, please contact us at Jumpmind and we can provide options.

Analytics

The new Analytics tab in the SymmetricDS Pro console provides five pre-built reports that give operations teams deep visibility into replication activity and health.

Reports are generated by the Refresh Analytics job, which runs every six hours by default. Each report screen shows when data was last refreshed and provides a Run Now button to trigger the job immediately. The Data retained for link shows the current retention period and opens a dialog to edit the purge.stats.retention.minutes parameter.

Table Heat Map — shows the total rows synchronized per table per day over a rolling window of up to 30 days. Cell colors indicate activity levels relative to other tables. Filters control the time range, the event type (insert, update, or delete), the metric (sent or loaded), and the number of tables shown.

Table Status Report — displays the insert, update, and delete activity for a single table over a rolling window. Includes an event-type donut chart, a stacked daily bar chart, and a daily breakdown table. Tables with significantly above-average activity are flagged with a HIGH ACTIVITY badge. Click a table name in the Table Heat Map to navigate directly to its Table Status Report.

Capture Health — shows whether CDC was actively capturing changes for each configured table, month by month, over a 13-month rolling window. Green cells indicate continuous active capture; yellow cells indicate configuration changes; orange cells indicate a partial capture gap; red cells indicate no capture for the entire month. Clicking a cell opens a detail dialog showing rebuild events or exact gap periods.

Node Backlog Heat Map — shows the average outgoing batch backlog per node per day. Summary cards surface the node with the largest current backlog and the node whose backlog is growing fastest. When offline nodes collectively hold 50% or more of the total backlog, a warning message identifies those nodes as a potential indicator of network trouble.

Cluster Traffic Heat Map — shows how replication traffic is distributed across cluster hosts per day, relative to the cluster average. An imbalance callout identifies hosts consistently handling more or less than their expected share of traffic. Filter by replication stage (Routed, Extracted, Sent, or Loaded), channel, and row or byte count.

Data Refresh

SymmetricDS 3.18 expands Data Refresh to support multiple, independently scheduled refresh jobs and extends replication to database views.

The Deploy Wizard automatically presents the new Data Refresh Configuration screen whenever the deployment includes tables or views that cannot use CDC — such as views, tables without primary keys on log-based SQL Server sources, or tables without compatible timestamp columns on time-based sources. Each CDC-ineligible table or view must be assigned a reload strategy and a schedule before the wizard can proceed. Predefined schedules such as hourly, daily, and weekly are available, and custom schedules can be created inline by selecting + Create New Schedule…​.

For post-deployment management, named Data Refresh jobs can be created and edited under Configure → Details → Jobs. Tables are assigned to a specific job using the Data Refresh Job field in Configure → Details → Table Routing. Tables configured for CDC remain on the default CDC assignment and are unaffected by any refresh job.

The Data Refresh Type field in Configure → Details → Table Routing controls how each table is refreshed when its assigned job runs:

  • Auto — chooses between a full reload or compare-and-repair.

  • Full — issues a table reload request with delete-first.

  • Full (truncate) — truncates the target table, then reloads all rows.

  • Differences — performs a compare-and-repair to sync only rows that differ. Requires a Compare & Repair license.

Views are now supported in replication on Microsoft SQL Server, Oracle, PostgreSQL, MySQL, and MariaDB source endpoints. The Configure Diagram’s Select Tables screen includes a Show Views checkbox to include views during setup.

Docker Image Hardening

The official SymmetricDS Pro Docker image now runs as the symds non-root system account (UID 1000 by default), satisfying Kubernetes security policies such as runAsNonRoot: true. Named volumes work without additional configuration; bind mounts require the host directory to be writable by the container UID. To use a different UID, pass the SYMDS_UID build argument at image build time.

A hardened image variant is available under the -hardened tag suffix (for example, jumpmind/symmetricds-pro:3.18.0-hardened). The hardened image uses a JRE-only base image to exclude the Java compiler toolchain and removes the Alpine package manager to reduce the post-compromise attack surface. Features that compile Java at runtime — Java jobs, Java routers, Java transforms, and Java extensions — are not available in the hardened image; use BeanShell scripting as an alternative for these features.

The hardened image supports running with all Linux capabilities dropped:

docker run --cap-drop=ALL -p 31415:31415 --name sym jumpmind/symmetricds-pro:3.18.0-hardened

In Kubernetes, the equivalent security context is:

securityContext:
  runAsNonRoot: true
  capabilities:
    drop:
      - ALL

Each hardened image includes an SBOM attestation verifiable via cosign for supply chain auditing and provenance verification.

OpenTelemetry Integration

SymmetricDS now publishes its built-in metrics through the OpenTelemetry (OTel) API, making them available to any OTel-compatible observability platform — including Prometheus (via the OTLP receiver), Grafana Cloud, DataDog, and Dynatrace.

Two integration modes are supported. When no global OpenTelemetry instance is present in the JVM, SymmetricDS initializes its own SDK using standard OTel autoconfiguration; exporters and other settings are controlled by OTEL_* environment variables (for example, OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_METRICS_EXPORTER). When an OTel Java agent is attached to the JVM, SymmetricDS detects the existing registered instance and routes all metrics through it automatically — no additional SDK configuration is required.

The metrics.opentelemetry.enabled parameter provides per-engine control and overrides the server-level OTEL_SDK_DISABLED flag for a single engine. This allows a server hosting multiple engines to enable or disable OTel publishing independently per engine.

Built-in Replication Metrics

SymmetricDS 3.18 introduces a built-in metrics framework that continuously collects and stores detailed statistics about the synchronization pipeline. Observations are aggregated into five-minute time windows and stored as summary statistics — average, minimum, maximum, standard deviation, and count — across four new tables: METRIC_KEY, METRIC_CONTEXT, METRIC_STATS_FLOAT64, and METRIC_STATS_INT64.

The following categories of metrics are collected automatically:

  • Server Connections — active connection reservations and utilization relative to the configured concurrent-worker limit.

  • Synchronization Pipeline — per-channel row and byte counts across each pipeline stage: routed, extracted, sent, received, and loaded.

  • Batch Status — per-node outgoing and incoming batch and row counts by status.

  • Queue Depth — unrouted row counts, data-gap counts, and oldest and newest unrouted row timestamps per channel.

  • Database Connection Pool — active, idle, and waiting connection counts and pool utilization.

  • Nodes — pull and push operation counts and elapsed times; registration, load, rejection, and disable counts.

  • Purge — row counts purged from the data, data event, and batch history tables.

  • Triggers — database trigger create, rebuild, and remove counts.

Metrics are published via the OpenTelemetry API under the scope symmetricds and are used to power the Analytics reports in SymmetricDS Pro.

Cluster Lock Recovery via JCS Peer Heartbeat

SymmetricDS 3.18 introduces a peer-to-peer heartbeat mechanism using Apache JCS lateral TCP cache to detect crashed cluster members and automatically recover their orphaned database locks.

Each endpoint broadcasts a heartbeat every 3 seconds to all known peers. When an endpoint misses three consecutive heartbeats — for example, because the JVM was killed by an out-of-memory condition, the container was evicted by the orchestrator, or the host was terminated — the surviving endpoints detect the stale heartbeat and immediately clear all database locks held by the crashed endpoint. This eliminates the previous behavior where surviving endpoints had to wait for the cluster.lock.timeout.ms expiry (default 2 hours) before they could acquire those locks.

In a multi-endpoint deployment where each JVM hosts multiple database endpoints independently, lock recovery is additionally scoped per endpoint. If only one endpoint on a JVM crashes while others remain healthy, only the locks held by that specific endpoint are cleared — the running endpoints are unaffected.

Multiple clusters for different environments — Production, Staging, and Testing — remain fully isolated even when deployed on the same orchestrator platform or shared subnet. Peer discovery is driven entirely by the SYM_NODE_HOST table: each endpoint only learns the hostnames of other endpoints that share the same database. Because each environment uses its own database, its SYM_NODE_HOST table contains only that environment’s endpoints, so JCS heartbeats are never exchanged across environments. As a second layer of defense, assigning a distinct cluster.jcs.port per environment provides network-level isolation and prevents accidental cross-environment traffic in scenarios where network segmentation is not strict.

The peer communication port is configured via the cluster.jcs.port property (default 1101, must be the same across all cluster members within an environment). Each cluster’s shared identity is the cluster partition ID: by default each node auto-generates its own random one locally on first startup (cached in conf/cluster-partition.uuid), so it must be pinned explicitly via cluster.partition.id (or the SYM_CLUSTER_PARTITION_ID environment variable) to the same value on every node that should belong to the same cluster. All endpoints must be reachable on the JCS port; peer messages are AES-encrypted with a SHA-512 header checksum, but the port should still be protected by network-level firewall rules and not exposed to untrusted networks.

Each cluster member’s peer identity — used for JCS peer discovery and for its row in SYM_NODE_HOST — is now resolved consistently from the single cluster.server.id parameter (defaulting to the container/OS hostname - recommended for most deployments!). The internal runtime.symmetric.cluster.server.id system property has been removed; use cluster.server.id to pin a stable, distinct identity per cluster member.

cluster.lock.enabled is now a startup-only parameter and is no longer database-overridable. Whether JCS peer-awareness starts at all is decided once, before any node or engine exists, from the file/environment value of this parameter; a SYM_PARAMETER override was never reliably honored against that already-made decision, and code that re-checked the live database value later could disagree with what actually started, silently skipping cluster-authentication checks or misreporting whether JCS clustering is active. Set cluster.lock.enabled in engine properties or as an environment variable before startup; changing it in the database (or via the admin console) has no effect and requires a restart to take effect.

Custom extensions implementing the following core interfaces should note these changes:

  • IClusterService — adds removeObsoleteNodeHosts(), which clears any cluster locks still held by a SYM_NODE_HOST entry older than cluster.peer.obsolete.ms, removes that entry, and also removes the corresponding peer from the in-memory JCS peer registry (IClusteredCacheManager.removePeer). Called automatically at the start of the outgoing purge job.

  • INodeService — adds updateNodeHostForCurrentNode(boolean bypassTrigger) (moved here from a private DataService method) so any caller can update the current node’s heartbeat with or without going through sync triggers.

  • IClusteredCacheManager and IClusterCacheCoordinator — Wrap JCS server-to-server communication and peer server discovery. Peer discovery also supports simpler discovery - SYM_NODE_HOST table. PRO version adds support of UDP broadcast, which might not route on most cloud VPCs (AWS, Azure, GCP, OCI) or managed Kubernetes networks. Discovery services are used where available to accelerate detection of container crashes (seconds versus the heartbeat job’s cadence, job.heartbeat.period.time.ms, 15 minutes by default).

Container Mode

SymmetricDS 3.18 adds first-class container support via the bin/sym --container command. This mode runs SymmetricDS as PID 1 inside the container, enabling proper signal handling and graceful shutdown behavior expected by container orchestrators.

Two HTTP health endpoints are available for container orchestrators:

/health/liveliness — returns HTTP 200 with the following body when SymmetricDS is running:

{
  "status": "UP"
}

/health/readiness — returns per-engine readiness status. When all engines are ready, it returns HTTP 200; when any engine is not ready, it returns HTTP 503:

{
  "engine_details": [
    {"engine_name": "corp-000", "status": "READY"}
  ],
  "status": "READY"
}

Database Health Check

SymmetricDS 3.18 adds a pre-flight health check of the runtime database connection that acts as a circuit breaker during database outages. Before each job run and before accepting an incoming push or pull, SymmetricDS verifies that a connection to the runtime database can be established. The check only opens and closes a connection, so a failure always means the connection could not be established — it is never triggered by ordinary SQL errors related to data or constraints.

Previously, a database outage caused every job to fail mid-work on each cycle with the same SqlException, flooding the logs and wasting remote work — for example, pull requests repeatedly re-extracting batches and inflating row transmit statistics. With the health check, the runtime database is declared unhealthy after db.health.check.failure.threshold consecutive connection failures (default 5). While unhealthy:

  • Jobs are skipped with a single warning per skipped run instead of a stack trace per failure.

  • Incoming push and pull requests are rejected with the code 671 "Service Not Ready" response, so remote nodes back off without starting work this server cannot finish.

  • The engine is reported as not ready on the /health/readiness endpoint, so container orchestrators stop routing to it.

  • The connection is not tested again until the db.health.check.retry.seconds wait period has elapsed (60 seconds by default).

After the wait period, the connection is retested. Two consecutive successful tests restore the healthy state, resume jobs, accept incoming syncs again, and report the engine as ready. Manually forced job runs bypass the check, giving operators a way to probe the database during an outage. Each connection test is time-bounded by db.pool.max.wait.millis, so a hanging connection attempt is treated as a failure instead of stalling the health check. The time and outcome of the most recent connection test are recorded and available from the engine API.

The feature is controlled by three new parameters:

  • db.health.check.enabled — enables the pre-flight health check (default true).

  • db.health.check.failure.threshold — consecutive connection failures before the runtime database is declared unhealthy (default 5).

  • db.health.check.retry.seconds — wait period between connection tests while unhealthy (default 60).

HikariCP Connection Pool

SymmetricDS 3.18 uses HikariCP as its default database connection pool, replacing Apache DBCP2. HikariCP ships with SymmetricDS and needs no setup. It replaces broken connections on its own after a database restart or network interruption, and opens new connections at a steady rate when many threads need one at once.

The pool is selected with the db.pool.type property in the engine properties file, set to hikari or dbcp2. DBCP2 remains fully supported.

Upgraded installations keep DBCP2. When upgrading from a version older than 3.18, the setup program adds db.pool.type=dbcp2 to every engine properties file that does not already set it. To switch an upgraded engine to HikariCP, change the property to db.pool.type=hikari and restart.

New HikariCP settings control connection lifetime, idle timeout, keepalive, and leak detection, and some DBCP2 settings are ignored under HikariCP. The Database Connection Pool appendix of the SymmetricDS User Guide compares the two pools property by property and covers tuning and TCP keepalive.

Logging Framework Changed to Logback

SymmetricDS 3.18 replaces Log4j2 with Logback as the logging implementation. SymmetricDS continues to log through SLF4J, so log output and logger names are unchanged.

The configuration file changes from conf/log4j2.xml to conf/logback.xml. The --debug command line option now uses conf/logback-debug.xml, and the blank configuration is conf/logback-blank.xml.

Existing configuration is converted during upgrade. The setup program translates your log4j2.xml into logback.xml, retires the old files with a .deprecated suffix, and repoints the startup scripts and service configuration. Loggers, levels, and the standard console and file appenders carry over without intervention.

A few Log4j2 constructs have no Logback equivalent and are left out of the converted file, each one recorded as a WARNING in logs/install.log. Review that file after upgrading if you used any of the following:

  • An appender other than Console, File, RollingFile, or SymRollingFile.

  • An appender filter, or a layout other than PatternLayout.

  • The FATAL level, which is converted to ERROR and therefore logs more than before. Change it to OFF to silence the logger completely.

The Logging chapter of the SymmetricDS User Guide contains a full translation guide, including a before and after example and a table mapping every Log4j2 element and attribute to its Logback equivalent.

Behavior changes worth noting:

  • The root level in the shipped logback.xml changed from INFO to ERROR. SymmetricDS logging is unaffected because its own loggers are set to INFO explicitly, but third-party libraries are quieter under the new default. This applies to new installations and to upgrades where the configuration was not converted; a converted configuration keeps its original root level. Add an explicit logger entry for any library whose output you rely on.

  • Logging configuration is now reloaded automatically. logback.xml ships with scan="true", so edits take effect within about a minute without restarting SymmetricDS. This makes it possible to enable debug logging for a live problem and turn it off again without an outage.

Spring Library Updates

SymmetricDS 3.18 upgrades to Spring Framework 7.x, which is a major version change from Spring 6.x. The upgrade also includes: * Spring Boot 4.x * Spring Data 4.x * Spring Security 7.1.x

Note: Java 21 or newer is now required; See also: [System Requirements].

Issues

New Features

3.18.0 (Pro)
SYM-7228 - File Sync-Only Endpoint
SYM-7404 - Cluster-aware Caching Service enhancement - object synchronization
SYM-7424 - Import endpoint and server startup parameters from environment variables
SYM-7425 - Import JVM and server config from environment variables
SYM-7426 - Add "--container” command-line parameter to the SYM utility for integration with Kubernetes/Docker
SYM-7434 - Table Data Changes Heatmap screen - Analytics
SYM-7436 - Node backlog heat map view - Analytics
SYM-7441 - Refresh Analytics job - Analytics
SYM-7454 - Add an Event Type filter to the Analytics → Table Heat Map screen
SYM-7455 - Add a Metric filter to the Analytics → Table Heat Map screen
SYM-7456 - Add a new screen under the Analytics tab for viewing row statistics for an individual table
SYM-7469 - Add sym_ table statistics to sym_console_table_stats
SYM-7491 - Add a parameter that determines what time zone reports are in
SYM-7501 - Add a REST API call for retrieving analytics report data
SYM-7505 - Analytics → Cluster Traffic screen
SYM-7510 - Minimum-privilege runtime account for container image
SYM-7512 - Add an Analytics → Capture Health screen that displays data from sym_trigger_hist
SYM-7535 - Add Readiness endpoint APIs for Kubernetes/Docker integration
SYM-7599 - Replicate data from Views
SYM-7600 - Assign Data Refresh job to tables ineligible for CDC (new Deploy wizard screen)
SYM-7615 - Differentiate Truncate- and Delete-based Data Refresh jobs and table capture assignments
SYM-7652 - Use the Vaadin Browserless Test framework to create baseline unit tests for the web console
SYM-7674 - Cluster-aware Caching Service for expiring locks from crashed containers
SYM-7736 - Add support for RETAINED computed columns on MS SQL Server
SYM-7738 - Add support for MATERIALIZED computed columns on Oracle
SYM-7748 - Convert existing Log4J2.xml configuration to Logback.xml configuration upon upgrade
SYM-7819 - Add variable support (using $() syntax) to the Column Match router
SYM-7924 - Request users to select a runtime database for log-based capture - Deploy Wizard

3.18.0
SYM-7271 - Implement Logback library for logging and support more log modes
SYM-7534 - Add Liveliness endpoint APIs for Kubernetes/Docker probe integration
SYM-7582 - Use HikariCP as default value for db.pool.type
SYM-7841 - Preserve original value for db.pool.type on upgrade from pre 3.18 version

3.18.1 (Pro)
SYM-7753 - Support SQL Server indexes on virtual computed columns (deterministic function)

3.18.1
SYM-7737 - Add support for STORED GENERATED columns on PostgreSQL
SYM-7739 - Add support for STORED GENERATED columns on MySQL
SYM-7747 - Add support for PERSISTENT or STORED GENERATED columns on MariaDB
SYM-7751 - Support MySQL virtual indexes (deterministic function)
SYM-7754 - Support MariaDB virtual indexes (deterministic function)

3.18.2 (Pro)
SYM-8136 - Authenticate outbound sync calls with JWT bearer token
SYM-8142 - Stream Sync Event notifications via REST API
SYM-8161 - Validate Bearer JWT on inbound sync requests
SYM-8172 - Document token-based authentication for Sync and Rest calls

Improvements

3.18.0 (Pro)
SYM-7365 - Support AWS Aurora-specific PostgreSQL endpoints (PRO edition)
SYM-7386 - Implement Docker Hardened Images (DHI community) for SymmetricPRO
SYM-7457 - Investigate whether the tab bar could be improved to better handle the addition of the Analytics tab
SYM-7519 - Add the sym_analytics_report table to the Pro support snapshot
SYM-7538 - Redesign the Pipelines Dashboard panel - Pipelines
SYM-7558 - Improvements per SonarCloud security and maintainability report
SYM-7603 - Make the Manage → Jobs and Configure → Details → Jobs screens use a specific icon for each custom job type
SYM-7610 - Update min Java requirement to 21 and IzPack to version 5.2.6 (Java 9+ to run Setup jar)
SYM-7633 - Don’t poll wrapper.log when running in a container mode
SYM-7701 - Exclude the Enterprise_Hub node from node selection in the Compare Wizard and the Load Data Wizard
SYM-7745 - New Health Check (database performance) test dialog
SYM-7798 - Support AWS Aurora-specific MySQL endpoints (Pro edition)
SYM-7803 - Support Google Cloud SQL for MySQL endpoints (Pro edition)
SYM-7810 - Align Column Match router with the PRO edition
SYM-7811 - Align Lookup Table router with the PRO edition
SYM-7812 - Align Subselect router with the PRO edition
SYM-7813 - Symmetric fails to start due to development mode - symmetric-vaadin-chartjs
SYM-7814 - Upgrade LobHandler and eliminate deprecated methods
SYM-7815 - Add new Column Segment retail-specific router
SYM-7816 - Support Google Cloud SQL for PostgreSQL endpoints (Pro edition)
SYM-7817 - Support Azure Database for PostgreSQL endpoints (Pro edition)
SYM-7833 - Log class name for all PRO descendants of AbstractDatabasePlatform
SYM-7868 - Enable REST API with key in environment variable
SYM-7879 - On the Deploy Wizard’s Endpoint Summary screen, hide the Capture Type edit icon for file sync endpoints
SYM-7904 - Activity Dashboard Panel - Test Failure
SYM-7942 - Switch DBConnectionPool monitor from 0-1 range to 0-100 range reporting percent of DB connections in use

3.18.0
SYM-7444 - Upgrade Spring Boot to 4.0.6
SYM-7497 - Retain exported foreign keys in table metadata cache
SYM-7623 - Refactor deprecated Spring’s LOB code
SYM-7634 - Prioritize start of registration node when multi-homed with client nodes
SYM-7638 - Add tables for built-in metrics to the support snapshot
SYM-7669 - Spring-Security version 7.0.6
SYM-7693 - Add Admin console user if password is preconfigured
SYM-7718 - Unit Tests for utility classes
SYM-7744 - Add Unit Tests
SYM-7763 - Add Unit Tests for DataUtils, DefaultValueHelper, ChannelUtils, ServletUtils
SYM-7830 - Upgrade Spring Boot to 4.1.0 to fix Jakarta and Tomcat dependencies
SYM-7848 - Database Health Tracker helps jobs and connection manager perform a preflight check of DB connection before running
SYM-7894 - Update Spring Security to version 7.1.1

3.18.1 (Pro)
SYM-7975 - Test available connections on performance check prior to deploy
SYM-7986 - Add Unit Tests for package com.jumpmind.symmetric.file
SYM-7989 - Add Unit Tests for package com.jumpmind.symmetric.db.bulk
SYM-8027 - Add Unit Tests for package com.jumpmind.symmetric.db.rabbitmq
SYM-8030 - Add Unit Tests for package com.jumpmind.symmetric.db.snowflake

3.18.1
SYM-7978 - Drop sym_node_channel_ctl during upgrade of SymmetricDS from pre 3.17 versions
SYM-7985 - Add Unit Tests for package org.jumpmind.symmetric.web
SYM-7988 - Add Unit Tests for package org.jumpmind.symmetric.io.data.transform
SYM-7990 - Add Unit Tests for package com.jumpmind.symmetric.log
SYM-7991 - Add Unit Tests for package com.jumpmind.symmetric.db.mssql
SYM-7992 - Add Unit Tests for package com.jumpmind.symmetric.compare
SYM-7993 - Add Unit Tests for package org.jumpmind.symmetric.db.derby
SYM-7994 - Add Unit Tests for package org.jumpmind.datasource.oracle
SYM-7995 - Add Unit Tests for package com.jumpmind.symmetric.db.db2
SYM-7996 - Add Unit Tests for package com.jumpmind.symmetric.db
SYM-7998 - Add Unit Tests for package org.jumpmind.symmetric.load
SYM-7999 - Add Unit Tests for package org.jumpmind.symmetric.route
SYM-8000 - Add Unit Tests for package org.jumpmind.symmetric.integrate
SYM-8001 - Add Unit Tests for package com.jumpmind.symmetric.db.cosmos
SYM-8002 - Add Unit Tests for package org.jumpmind.symmetric.io.data.reader
SYM-8003 - Add Unit Tests for package com.jumpmind.symmetric.util
SYM-8004 - Add Unit Tests for package org.jumpmind.symmetric.transport.file
SYM-8005 - Add Unit Tests for package org.jumpmind.db.platform.sqlite
SYM-8007 - Add Unit Tests for package org.jumpmind.symmetric.web.compression
SYM-8010 - Add Unit Tests for package org.jumpmind.symmetric.db.hsqldb
SYM-8011 - Add Unit Tests for package com.jumpmind.symmetric.db.openedge
SYM-8012 - Add Unit Tests for package com.jumpmind.symmetric.db.tibero
SYM-8013 - Add Unit Tests for package com.jumpmind.symmetric.http
SYM-8014 - Add Unit Tests for package org.jumpmind.symmetric.wrapper
SYM-8015 - Add Unit Tests for package org.jumpmind.db.platform.nuodb
SYM-8016 - Add Unit Tests for package org.jumpmind.db.platform.greenplum
SYM-8017 - Add Unit Tests for package org.jumpmind.db.platform.hsqldb2
SYM-8019 - Add Unit Tests for package com.jumpmind.symmetric.db.oracle
SYM-8020 - Add Unit Tests for package org.jumpmind.db.platform.voltdb
SYM-8021 - Add Unit Tests for package org.jumpmind.db.platform.raima
SYM-8022 - Add Unit Tests for package org.jumpmind.symmetric.io.data
SYM-8024 - Add Unit Tests for package org.jumpmind.db.platform.db2
SYM-8025 - Add Unit Tests for package org.jumpmind.db.platform.redshift
SYM-8026 - Add Unit Tests for package org.jumpmind.symmetric.ext
SYM-8028 - Add Unit Tests for package org.jumpmind.symmetric.db.ingres
SYM-8029 - Add Unit Tests for package org.jumpmind.symmetric.transport.internal
SYM-8031 - Add Unit Tests for package org.jumpmind.symmetric.transport.http

3.18.2 (Pro)
SYM-7551 - DB2 AS400 Support For Log Mining of LOBS from Journal Entries
SYM-7767 - Add parameter to override Azure Blob File Sync Url
SYM-8037 - Add Unit Tests for package com.jumpmind.symmetric.route
SYM-8079 - Set a lock timeout to prevent blocking DDL reader metadata queries (MS SQL Server)

3.18.2
SYM-7689 - AS400 Journal receiver rollover support
SYM-7983 - Add Unit Tests for package org.jumpmind.driver
SYM-8008 - Add Unit Tests for package org.jumpmind.symmetric.service.impl
SYM-8009 - Add Unit Tests for package org.jumpmind.symmetric.job
SYM-8018 - Add Unit Tests for package org.jumpmind.properties
SYM-8032 - Add Unit Tests for package org.jumpmind.symmetric.extract
SYM-8033 - Add Unit Tests for package org.jumpmind.db.sql
SYM-8034 - Add Unit Tests for package com.jumpmind.symmetric.db.bigquery
SYM-8035 - Add Unit Tests for package org.jumpmind.datasource.common
SYM-8036 - Add Unit Tests for package org.jumpmind.db.platform.sqlanywhere
SYM-8038 - Add Unit Tests for package org.jumpmind.db.platform.hsqldb
SYM-8067 - Log effective DB connection pool size at startup and warn when concurrent workers exceed it
SYM-8076 - Optimize slow OBJECT_NAME()/OBJECTPROPERTY() from WHERE clauses of MsSqlDdlReader catalog queries (table metadata on MS SQL Server)
SYM-8081 - Your license will expire warning shows negative value for days
SYM-8082 - Optimize read of column metadata for tables (MS SQL Server)
SYM-8093 - Update contact options in README file
SYM-8094 - Add Unit Tests for package com.jumpmind.symmetric.console.service.impl
SYM-8098 - Client should expire reservation cookie when the server returns SC_SERVICE_BUSY
SYM-8110 - Reduce unnecessary boxed wrapper usage
SYM-8115 - Upgrade H2 library to 2.5.252
SYM-8144 - Additional logging for Gap Analysis during long Routing job runs
SYM-8152 - Installer inspects running processes to prevent file access issues
SYM-8156 - Upgrade Apache Commons Lang3 to 3.20.1 or later to remove the JDK 25 three-letter time zone warnings

Bug Fixes

3.18.0 (Pro)
SYM-7191 - Prohibit clustered Initial load job when storage is not clustered
SYM-7383 - Adjust LogMiner replication procedure parameters for AWS Aurora PostgreSQL
SYM-7697 - Before and during deployment, the log contains many EngineMetricsService warning messages
SYM-7703 - Installing the Kafka module causes startup error due to Jackson version mismatch
SYM-7706 - The Import buttons in the web console display the imported file name
SYM-7709 - When the error badge in the top bar is visible, the node and user dropdowns collapse
SYM-7719 - The Help section within a Configure → Details form can be cut off without a scrollbar
SYM-7730 - NullPointerException when unregistering the current node
SYM-7733 - The db.client.connection.count metric doesn’t get updated
SYM-7735 - Add support for Database Connection Pool metrics in HikariCP mode
SYM-7795 - Postgres log miner fails to parse Aurora Postgres database URL
SYM-7824 - Rename $(HOSTNAME) template entry to $(hostName) to match existing variable substitution logic
SYM-7869 - MAC OS - Instance ownership clash (Hostname and MAC address)
SYM-7870 - When configuring bidirectional file sync, the Configure Diagram only shows that a directory is configured in one direction
SYM-7871 - Closing the Configure Diagram’s Define Endpoint screen when in the pipelines view causes unexpected behavior
SYM-7872 - Blank Time-Based Column Per Table in the '<ENDPOINT>' Endpoint Screen
SYM-7874 - Uninstalling a node via the Manage → Nodes screen results in errors being logged
SYM-7875 - Switching between nodes causes the Configure Diagram’s confirm dialog to pop up unnecessarily
SYM-7876 - It’s possible to link a file sync endpoint to a non-file sync endpoint in the Configure Diagram
SYM-7877 - The Configure Diagram’s Define Endpoint screen displays an inaccurate message when configuring multi-primary file sync
SYM-7878 - In the Configure Diagram, an empty link between 2 file sync endpoints is labeled "0 tables"
SYM-7883 - Node’s own shutdown can spuriously declare a live peer crashed and clear its locks
SYM-7885 - SymmetricDS fails to start on Sybase ASE for integration tests - min, max, avg are reserved words in new metric stats tables
SYM-7886 - Log miner throws a ClassCastException when a view is configured for data refresh
SYM-7888 - Existing logback.xml file gets overwritten during an upgrade
SYM-7889 - A SqlException occurs when connecting to a database using the Connect Database Wizard
SYM-7893 - Shorten index name on new tables to fit Firebird max identifier length
SYM-7905 - On Deployment of Pipeline the Enterprise Hub does not get past Permissions check
SYM-7907 - Undeployed changes in the Configure Diagram are lost after a restart
SYM-7917 - Deployment fails if a new endpoint’s external ID contains a space
SYM-7919 - In the Configure Diagram, selecting a file sync endpoint displays a Test Connection button that expects a JDBC URL
SYM-7926 - Newly registered node is missing cluster lock until restart
SYM-7937 - Computed column expression gets corrupted on target table creation MS SQL Server
SYM-7946 - Fix Playwright e2e suite broken by Vaadin 25 upgrade
SYM-7950 - Upgrade Jetty version to 12.1.10
SYM-7952 - Upgrade jackson-databind version to 2.18.8
SYM-7953 - Upgrade HttpCore5 version to 5.4.3+
SYM-7955 - Upgrade Vaadin version 25+ to pick up DOMPurify 3.4.12+
SYM-7960 - Postgres endpoint deployment failure
SYM-7963 - Log-based vanilla Postgres endpoint shows up as a Google Cloud SQL for PostgreSQL endpoint in the web console
SYM-7965 - 'CURRENT_TIMESTAMP' in MetricsRepositorySqlMap is not recognized by Sybase ASE in 3.18
SYM-7972 - Container instance ID regenerates on restart because MAC-address fingerprint validation is unreliable in containers

3.18.0
SYM-7167 - Channel name (max 128 chars) copied into queue name (max 25 chars) in sym_node_communication
SYM-7499 - MySQL and MariaDB Bulk Writer should fallback when FK cascade on delete exists
SYM-7657 - Address logback licensing conflict
SYM-7699 - Repeated sym_metric_stats_int64 primary key violations
SYM-7704 - The change-log.txt file links to the old issue tracker
SYM-7711 - With a H2 runtime database, reconfiguring a sym_ table’s triggers throws a "Table not found" error
SYM-7712 - The triggers.removed.count metric never gets incremented
SYM-7714 - Triggers created when Sync Triggers runs for the first time aren’t counted toward the triggers.created.count metric
SYM-7715 - The description for the triggers.rebuilt.count metric is inaccurate
SYM-7716 - The *.incoming.count metrics never get updated
SYM-7717 - The metric IDs in the user guide differ from the database and codebase
SYM-7720 - Most sym_metric_context columns are missing a description
SYM-7722 - The rows.unrouted.channel.count metric doesn’t get updated
SYM-7723 - The rows.create.time.min and rows.create.time.max metrics don’t track unrouted data as expected
SYM-7724 - The rows.create.time.min and rows.create.time.max metrics don’t track custom channels
SYM-7725 - Support tracking custom channels via Built-in Synchronization Metrics
SYM-7726 - The rows.sent.errors metric never gets updated
SYM-7732 - When the Watchdog job disables a node that uses internal communication, the client side of the process never executes
SYM-7749 - Lacking button to download logs while running in container mode
SYM-7750 - Ignore indexes on computed, but not retained columns (MS SQL Server) because they cannot be created on target database
SYM-7799 - ClassCastException when reading metric stats from MySQL database
SYM-7821 - Initialize ClusteredCacheManager in the integration test setup
SYM-7822 - Integration test task does not set sym.keystore.file
SYM-7828 - testRefreshLockUpdatesNodeHostHeartbeat must have isValidLicense set to true to execute test
SYM-7882 - Misleading debug log message in ClusteredCacheManager (inverted condition text)
SYM-7887 - Log4j → Logback migration isn’t documented
SYM-7900 - Launch scripts in bin/ directory fail when install path contains spaces
SYM-7908 - Windows service wrapper JVM runs without -Xms/-Xmx and commits ~1/64 of physical RAM per service
SYM-7928 - The db.pool.type parameter’s default value is documented incorrectly
SYM-7929 - Deferred foreign keys and indexes silently dropped when an initial load uses multiple extract threads
SYM-7930 - Console accepts a target-initiated initial load that can never reach the source node
SYM-7935 - Log4j → Logback migration failure: logback.xml packaged in installation is confused for custom costumer configuration
SYM-7968 - Built-in Metrics rows.create.time.min/max are never cleared after unrouted data reaches zero
SYM-7969 - Unrouted Data (create-time) metric includes already-routed rows when data gaps exceed the greater-than-query threshold
SYM-7970 - Refresh Unrouted Data Metrics Job might silently write nothing when it runs on a non-routing cluster node

3.18.1 (Pro)
SYM-7936 - Target initiated initial load allowed in UI even if group link missing
SYM-7964 - Instance ownership clash in Eclipse on MAC when local dev environment doesn’t have cluster.lock.enabled=true
SYM-7977 - Uninstalling SymmetircDS objects, leaves performance test table behind
SYM-7980 - Declare SYM_PERF_TEST in TableConstants

3.18.1
SYM-7966 - Validate file sync using checksums or file sizes
SYM-8045 - PostgresBulkCopyCommandTest unit test failure
SYM-8049 - Unable to dismiss the TLS certificate expiration notification
SYM-8058 - SymmetricTargetValidatorTest.installMode_pathWithTab_isRejected fails on Windows
SYM-8065 - Add monitor to alert about node group links whose target group has no members
SYM-8083 - Trigger template hash is computed non-thread-safe (rebuilds more often than necessary)
SYM-8085 - Race when concurrent pull requests register the same External_ID

3.18.2 (Pro)
SYM-7713 - On dialects that support create or replace, triggers that are rebuilt count towards the triggers.created.count metric
SYM-7769 - Logging levels can’t be configured for the Oracle log miner and some other PRO classes
SYM-7913 - AS400 journal read process has no upper bound or row cap, so a log miner that falls behind diverges instead of catching up
SYM-7914 - In AS400 log miner the user_name is not captured for UPDATE and DELETE events
SYM-8039 - AS400 log miner stalls permanently after one cycle in rollover-safe position modes because getCurrentScn() returns a cached value the framework’s next-ID bookkeeping always overtakes
SYM-8040 - AS400 log miner does not reset lastReadPosition per pass, so empty passes report a stale resume point and advanceOnEmptyPass is never reached
SYM-8041 - AS400 log miner row cap advances the resume position past entries that were read but not emitted, silently losing changes, and the cap ships enabled
SYM-8042 - Changing as400.journal.position.mode, or adding a journal, silently discards every in-flight change and logs it at INFO
SYM-8086 - FK error caused by parent row provided by Change Tracking out-of-order when Insert and Update are close together (MS SQL Server)
SYM-8103 - Incompatible Datetime insight produces False-Negative for load-only SQL Server node
SYM-8104 - Fix how trigger rebuilds are being recorded in TriggerRouterService
SYM-8131 - Upgrade FasterXML Jackson suite to version 3.2.2
SYM-8133 - PostgreSQL log miner syncs empty BLOB values as null
SYM-8134 - WildcardTest fails with Postgres log mining: wildcard trigger expression used as table name
SYM-8139 - PostgreSQL log miner does not recognize case-sensitive table/column names
SYM-8160 - Wizard building partial load ignores selected trigger history for Wildcard-schema triggers
SYM-8182 - Oracle Log Miner: Fix timezone-dependent failures in LogRowConverterTest

3.18.2
SYM-8099 - Skip reservation process, when filtered list of batches to push is empty
SYM-8100 - Abandoned Push-Reservations occupy the connection pool until timeout
SYM-8113 - Documentation still states the Connection Pool insight is only compatible with db.pool.type=dbcp2
SYM-8122 - MySql trigger rebuild fails with "Trigger already exists" when a trigger’s configured table name differs in case from the table’s actual name
SYM-8137 - SYMADMIN create-sym-tables command fails with exception
SYM-8205 - Full loads stuck in finalize step on group links with file sync and data sync

3.18.3 (Pro)
SYM-8201 - ProcessInfoPanel throws exception when accessing the panel

Tables

The following changes were made to the definition of configuration and runtime tables. Table changes are applied to the database automatically using data definition language (DDL) during startup.

New Tables

Table Name Description

sym_metric_key

Metric header - a dimension table that maps a compact surrogate key to a metric time-series identity (metric ID, hostname, engine name).

sym_metric_context

Dimension table mapping a surrogate context_id to a set of up to three metric attribute name/value pairs.

sym_metric_stats_float64

Fact table for floating-point observations aggregated across a time window (per metric). Statistics are time-weighted using a step-function model.

sym_metric_stats_int64

Fact table for integer observations aggregated across a time window (per metric). Statistics are time-weighted using a step-function model. Integer variant: min, max, avg, mean are BIGINT.

sym_analytics_report (Pro)

Report data generated by the Refresh Analytics job for the web console’s Analytics tab

sym_perf_test (Pro)

Scratch table used by the DB Performance monitor and the Database Performance test dialog to measure database round-trip latency.

sym_sync_event (Pro)

Outbox of sync events (engine, batch, and load changes) waiting to be delivered to subscribers such as the sync event stream.

New Columns

SYM_CONSOLE_TABLE_STATS (Pro)
Column Name Description

is_system_table

Whether or not this row contains statistics for a system table.

SYM_NODE_HOST
Column Name Description

cluster_partition_id

Local cluster partition ID to facilitate local-networked cluster communication while keeping Production separate from non-Production environments.

security_mode

The security mode of the runtime environment. 'standard' indicates a JDK is available; 'restricted' indicates a JRE-only environment where Java compilation features are unavailable.

Modified Tables

SYM_CHANNEL
  • queue size changed from 25 to 128

SYM_EXTRACT_REQUEST
  • Added index idx_er_nd_ld_src_sb (node_id, load_id, source_node_id, start_batch_id)

SYM_MONITOR_EVENT (Pro)
  • host_name size changed from 60 to 255

SYM_NODE_COMMUNICATION
  • queue size changed from 25 to 128

Parameters

The following changes were made to add new parameters, modify their default value, modify their description, or remove them from use.

New Parameters

analytics.report.time.zone (Pro)

The time zone used to group analytics report data by date. Accepts IANA zone IDs (e.g., UTC, America/New_York) or GMT offsets (e.g., GMT+05:30). When blank, defaults to the JVM time zone (user.timezone). Note: database timestamp columns carry no time zone info. JDBC interprets them using user.timezone to produce Java Date values (epoch millis). If the database server’s time zone differs from user.timezone, date boundaries may be misaligned regardless of this setting. (Default: )

as400.decimal.blank.as.zero (Pro)

Controls the value the AS400 log miner emits when a packed-decimal field cannot be decoded because it is blank/uninitialized (all EBCDIC spaces, e.g. a numeric column added to a file after rows already existed) or otherwise contains non-BCD bytes. true (default): emit 0, matching the AS/400 numeric default and avoiding NOT NULL violations on the target. false: emit NULL (use when a blank value must remain distinct from zero, since implying 0 can affect downstream calculations). Applies per deployment. Either way a one-time WARN is logged with the table, column, and raw hex so the source data quality issue stays visible. (Default: true)

as400.journal.position.mode (Pro)

Controls how the AS400 log miner reads journal entries and tracks where it left off, which determines whether changes can be missed when a journal receiver rolls over (CHGJRN or a full receiver). legacy: Tracks the journal sequence number against the current receiver only; this is the original behavior and is unchanged on upgrade. timestamp: Reads the entire receiver chain and resumes by entry timestamp, which stays correct across receiver rollovers and sequence resets on IBM i 7.1 and later. receiver: Reads the entire receiver chain and resumes from the exact receiver and sequence using the per-row receiver columns available on IBM i 7.3 and later; used only with a single journal (with multiple journals it falls back to timestamp). auto: Uses receiver mode on a single journal on IBM i 7.3 and later, and timestamp mode on older releases or when multiple journals are configured. Defaults to legacy so existing deployments are unchanged; set to auto (or timestamp) to enable rollover-safe capture, and set back to legacy to restore prior behavior. IMPORTANT: changing this value, in either direction, is a reload boundary, not an incremental resume. Each mode tracks its own resume position, so the first cycle after a change bootstraps from the current end of the journal and everything captured under the previous mode but not yet mined is discarded permanently. This is logged loudly (WARN) when it happens. Plan a mode change like a reload: quiesce the source first, or accept the gap. (Default: legacy)

as400.journal.read.window.seconds (Pro)

Upper bound, in seconds of journal time, on how far forward one AS400 mining pass reads in a rollover-safe position mode (as400.journal.position.mode timestamp or receiver). The bound is passed to DISPLAY_JOURNAL as ENDING_TIMESTAMP, a function argument, so the journal read stops at the server instead of being driven to the end of the receiver chain. Without it a pass that falls behind reads an ever larger span and each pass takes longer than the last, so the miner diverges rather than catching up. The window is also clamped to the current system clock, so a caught-up miner skips the journal read entirely. Raise it to catch up faster after a long outage; lower it to shorten each pass. Set to 0 to read to the end of the journal (the previous unbounded behavior). Requires IBM i 7.2 or later; ignored on 7.1, which has no ENDING_TIMESTAMP argument. The bound is a timestamp in both modes, including receiver mode, whose resume position is a (receiver, sequence) pair. A sequence cannot bound a chain-spanning read: sequence numbers restart per receiver, so across a chain they are neither unique nor monotonic, and ENDING_SEQUENCE stops at its first match rather than at the end of the window. entry_timestamp is monotonic across the chain, so it is the only safe bound. (Default: 300)

as400.journal.table.filter.max.tables (Pro)

Maximum number of tracked tables for which the AS400 log miner adds a table-name filter to the journal read SQL, so entries for untracked tables never leave the server. Transaction boundaries always pass the filter, and the exact Java-side check still applies. Set to 0 to disable the SQL filter; above this count the filter is not generated and all entries are filtered in Java as before. (Default: 500)

cluster.jcs.port

TCP port used by Apache JCS lateral cache for cluster peer-to-peer communication. All nodes in the cluster must use the same port. Each node sends a heartbeat to its peers at the interval defined by cluster.peer.heartbeat.ms. If a peer misses three consecutive heartbeats, its database locks are cleared automatically. Security note: JCS lateral TCP communication is not encrypted or authenticated. Messages are plain serialized Java objects sent over raw TCP. Cluster nodes must be deployed on a private, firewalled network. This port should not be exposed to untrusted hosts, as a rogue node could spoof heartbeats to clear locks or trigger a duplicate-instance shutdown. (Default: 1101)

cluster.keystore.seed

Base64-encoded 256-bit AES key to seed the sym.secret keystore entry on first startup. All cluster nodes must share the same value so that encrypted values stored in the database can be decrypted by any node. Equivalent environment variable: SYM_CLUSTER_KEYSTORE_SEED (Default: )

cluster.partition.id

Optionally pins the cluster partition ID: a shared identity that lets JCS lateral cache peers recognize each other as belonging to the same cluster/environment. If left blank, SymmetricDS generates a random one and caches it in conf/cluster-partition.uuid so restarts of the same installation converge on the same value without a database round-trip. Resolved without database access at JCS startup, so this value cannot be overridden from the database — set it explicitly (or via the environment variable below) when multiple nodes need to share one partition. Equivalent environment variable: SYM_CLUSTER_PARTITION_ID (Default: )

cluster.peer.discovery

Peer discovery mechanism for the cluster cache lateral transport. Valid values are: db, udp, static db - This mode uses SYM_NODE_HOST-based discovery, which is already faster than timeout setting used in the older versions. udp - This mode uses UDP multicast to discover server peers on the same subnet (local network only). static - This mode uses pre-configured list of all expected hostnames or IP addresses (populated in the cluster.peer.discovery.static.servers) Note: udp and static modes require SymmetricDS PRO edition. (Default: db)

cluster.peer.discovery.static.servers

Comma-separated list of host:port pairs for all expected cluster peers, used only when cluster.peer.discovery is set to static. Example: sympod1:1101,sympod2:1101,sympod3:1101 (Default: )

cluster.peer.heartbeat.ms

Interval in milliseconds between heartbeat messages sent to cluster peers via JCS lateral cache. Shorter values detect crashes faster but increase network traffic. (Default: 3000)

cluster.peer.obsolete.ms

Age in milliseconds after which a peer’s cluster-membership record (crashed or gracefully left) is purged entirely, since it is no longer relevant to anything, including lock-staleness checks. Must be well greater than cluster.peer.stale.ms since a peer stays stale (but retained) long before it becomes obsolete (and removed). Default is 8 hours. Also governs when a sym_node_host row for a different instance id is presumed decommissioned/offline (allowing a new instance to break locks at startup instead of failing). (Default: 28800000)

cluster.peer.stale.ms

Age in milliseconds after which a peer’s last heartbeat is considered stale and the peer is treated as crashed. Must be greater than cluster.peer.heartbeat.ms to allow at least one missed heartbeat before declaring a peer dead. Default is 9 seconds (three missed heartbeats at the default 3-second interval). (Default: 9000)

console.admin.user.pwd (Pro)

Auto-provision the built-in 'symadmin' admin user on startup. When set, the user is created (or its password updated) every time the engine starts. Only takes effect on registration servers (registration.url is blank or equals sync.url). If the user already exists its password is overridden and a warning is logged. Set via this property or environment variable SYM_CONSOLE_ADMIN_USER_PWD. (Default: )

container.mode.enable

Set to true automatically when SymmetricDS is launched with --container. (Default: false)

db.health.check.enabled

Enables a pre-flight health check of the runtime database connection before each job run and before accepting an incoming push or pull. The check only opens and closes a connection, so a failure always means the connection could not be established. (Default: true)

db.health.check.failure.threshold

Number of consecutive connection test failures before the runtime database is declared unhealthy. While unhealthy, jobs are skipped and incoming syncs are rejected as service not ready for a wait period of db.health.check.retry.seconds, after which the connection is tested again (twice). (Default: 5)

db.health.check.retry.seconds

Number of seconds to wait between connection tests while the runtime database is unhealthy. Prevents overwhelming an unhealthy database server with connection requests. (Default: 60)

extension.use.legacy.interface.enabled

Whether to use legacy extension interfaces (IReloadVariableFilter, IExtractDataFilter, ITableResolver) that accept Table instead of the newer interfaces that accept Relation. (Default: false)

file.sync.azure.url (Pro)

Azure Blob Storage Url to be used. Could be set when using Azurite as a blob storage emulator and not Azure. (Default: )

force.bulk.write.with.on.delete.cascade (Pro)

Force the MySQL and MariaDB bulk writers to use bulk mode, even when the table is a parent in a foreign key relationship, and the delete is set up with CASCADE ON DELETE (Default: false)

http.concurrent.reservation.release.on.close.enabled

When enabled, a push reservation taken by a HEAD request is released as soon as the HTTP connection that carried it closes, instead of waiting for http.concurrent.reservation.timeout.ms to expire. Only safe when client nodes connect directly to this server. It is skipped automatically for requests that carry a forwarding header (Forwarded, X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto or X-Real-IP), because a load balancer can close its backend connection while the client is still about to push. (Default: false)

http.jwt.client.send.enabled (Pro)

Send the JWT in the http.jwt.client.token parameter as an "Authorization: Bearer" header on outbound sync requests, in addition to the node’s own authentication. (Default: false)

http.jwt.client.token (Pro)

The JWT to send as a bearer token on outbound sync requests when http.jwt.client.send.enabled is true. The value is read from the file named by http.jwt.client.token.location and refreshed while running, so replacing the file takes effect without a restart. It cannot be set here. An expired JWT is still sent, and the JWT is not validated. (Default: )

http.jwt.client.token.location (Pro)

The file that holds the JWT for http.jwt.client.token. A relative path is resolved against the SymmetricDS home directory. (Default: security/sync_token.jwt)

http.jwt.server.algorithms (Pro)

Comma-separated list of signing algorithms to accept. The algorithm must also suit the key that the issuer publishes for the JWT’s key id. Unsigned ("none") and HMAC tokens are never accepted. (Default: ES256)

http.jwt.server.allowed.client.apps (Pro)

Comma-separated list of client_app_id claim values to accept. Leave blank to accept any client app. Only the JmcJwtValidator checks this. (Default: symmetricds)

http.jwt.server.audiences (Pro)

Comma-separated list of audiences to accept. A JWT must name at least one of them in its "aud" claim. Leave blank to accept any audience. (Default: )

http.jwt.server.clock.skew.seconds (Pro)

The tolerance for clock differences when checking the expiration (exp) and not-before (nbf) claims of a JWT. (Default: 30)

http.jwt.server.enforce.enabled (Pro)

When false, a sync request without a valid JWT is still allowed, and the failure is logged once per node every 10 minutes. Use it to roll tokens out to nodes before requiring them. REST API calls always require a valid JWT or API key. (Default: true)

http.jwt.server.issuer (Pro)

The issuer that JWTs must name in their "iss" claim, matched exactly. Required when http.jwt.server.validation.enabled is true. (Default: )

http.jwt.server.jwks.cache.time.ms (Pro)

How long to keep the fetched JSON Web Key Set before fetching it again, in milliseconds. A key id that is not in the cached set triggers an earlier fetch, at most every 30 seconds. (Default: 300000)

http.jwt.server.jwks.url (Pro)

The URL of the issuer’s JSON Web Key Set. Leave blank to use <issuer>/.well-known/jwks.json. It must use https. (Default: )

http.jwt.server.node.id.claim (Pro)

The claim that must equal the ID of the node making the request, so that a token can only be used by the node it was issued to. Use a dotted path for a nested claim, such as tags.business_unit_id. Registration requests are not checked, because the node does not have a node ID yet. Leave blank to skip this check, which lets any node use any other node’s token, and a warning is logged at startup. (Default: sub)

http.jwt.server.offline.leniency.minutes (Pro)

How long past its expiration a JWT is still accepted while the issuer is unreachable, so that nodes keep syncing through a network outage that prevents them from getting a new token. Once the issuer can be reached again, expired JWTs are rejected. (Default: 4320)

http.jwt.server.required.scopes (Pro)

Comma-separated list of scopes that JWTs must all include. Leave blank to accept any scope. Only the JmcJwtValidator checks this. (Default: device)

http.jwt.server.validation.class (Pro)

The class that validates JWTs, with one implementation per identity provider. It must extend com.jumpmind.symmetric.security.jwt.AbstractJwtValidator and have a public constructor that takes a JwtValidationSettings, an IJwksCache, an IdpReachability and a java.time.Clock. The default, and the only built-in validator, is com.jumpmind.symmetric.security.jwt.JmcJwtValidator, which validates the JWTs of the Jumpmind Commerce identity provider. (Default: com.jumpmind.symmetric.security.jwt.JmcJwtValidator)

http.jwt.server.validation.enabled (Pro)

Require a valid JWT, sent as an "Authorization: Bearer" header, on inbound sync requests (push, pull, ack, registration and the rest that need a security token). The JWT is verified locally against the issuer’s JSON Web Key Set, which is fetched from the issuer and cached on disk. This is in addition to the node’s security token, not a replacement for it. A valid JWT is also accepted in place of a missing or invalid REST API key, for read-only (GET) REST API calls. Requires an enterprise license; without one this parameter has no effect. The other http.jwt.server parameters are read at startup. Because this parameter can be overridden in the database, it can be turned off without a restart if the issuer becomes unavailable. (Default: false)

http.session.sticky.reset.enabled

When a push or pull is rejected with SC_SERVICE_BUSY (670), clear all cookies this JVM’s CookieManager holds for that target host (e.g. a load balancer’s session-affinity cookie) so the next request can be routed to a cluster member with reservation capacity. All cookies for the host are cleared, not just a named one, because a customer’s load balancer can create or rename affinity cookies in ways that cannot be reliably identified by name. Requires server.http.cookies.enabled=true; otherwise a no-op. Not recommended for load balancers that apply session affinity (sticky sessions) by source IP rather than by cookie. (Default: false)

job.purge.metric.stats.cron

This is when the purge metric stats job will run. (Default: 0 0 0 * * *)

job.refresh.analytics.cron (Pro)

This is when the Refresh Analytics job will run. (Default: 0 0 */6 * * *)

job.refresh.backlog.report.period.time.ms

This is how often the refresh backlog report job will run. (Default: 900000)

job.refresh.unrouted.data.metrics.period.time.ms

This is how often the refresh unrouted data metrics job will run. (Default: 900000)

log.cache.entries.max (Pro)

Maximum number of recent log entries retained in memory for the Manage Logging screen. (Default: 1000)

log.miner.mssql.history.view.enabled (Pro)

For SQL-Server log miner, query the change table using a reconstructed history view that splits each net change into its implied insert, update, and delete operations, instead of relying on SQL-Server’s default net change per row. This allows rows that were inserted and then updated within the same mining window to be synced as separate insert and update events. (Default: false)

mssql.metadata.lock.timeout.ms (Pro)

Milliseconds a SQL Server DDL-reader metadata query (catalog/system-view reads used to build table structure) will wait for a lock before giving up, instead of hanging indefinitely behind DDL, an online index rebuild, or a long-running transaction. Set to -1 to wait indefinitely. (Default: 30000)

purge.metric.stats.retention.minutes

This is the retention for how long metric interval statistics will be kept in the metric_stats_float64 and metric_stats_int64 tables. Orphaned metric_context rows are also removed. Note that data will be purged only if the purge metric stats job is enabled. The minimum value is 10,080 minutes (one week). (Default: 525600)

purge.sync.event.retention.minutes (Pro)

This is the retention time for how long sync events will be retained (Default: 10080)

rest.api.default.key (Pro)

Alternative way to provide a REST API key as a startup parameter, instead of creating a key via the console. Must be at least 32 characters long, otherwise it has no effect. REST API access still requires rest.api.enable=true. (Default: )

rest.stream.buffer.events.max (Pro)

The maximum number of events buffered in memory for a sync event stream. When the buffer is full, events are still delivered from the database. (Default: 500)

rest.stream.keepalive.seconds (Pro)

The number of seconds without an event before the sync event stream sends a keepalive. (Default: 5)

rest.stream.poll.seconds (Pro)

The number of seconds between checks of the database for sync events not yet delivered, such as events recorded by other members of a cluster. Only used when clustering is enabled. (Default: 1)

start.purge.metric.stats.job

Whether the purge metric stats job is enabled for this node. (Default: true)

start.refresh.analytics.job (Pro)

Whether the Refresh Analytics job is enabled for this node. (Default: true)

start.refresh.backlog.report.job

Whether the refresh backlog report job is enabled for this node. (Default: true)

start.refresh.unrouted.data.metrics.job

Whether the refresh unrouted data metrics job is enabled for this node. (Default: true)

sync.event.enabled

Enables notifying ISyncEventListener extension points when a batch ends or a load starts or ends. The built-in listener records these events, along with engine events, so they can be delivered by the sync event stream of the REST API. It’s only available in the Pro edition and requires an enterprise license. (Default: false)

Modified Parameters

cluster.server.id

This should be a unique network hostname name used to identify SymmetricDS server or container in both clustered cache manager, clustered job locks and node communication locks. Defaults to the container/OS hostname. Recorded in the SYM_NODE_HOST runtime table. Resolved (before database connection is available) at startup via system property or environment variable, falling back to the local hostname). WARNING: Modifying this value is not recommended, unless testing in a non-Production environment or cluster.lock.enabled=false (Old Default: ) (New Default: $(hostName))

db.pool.max.idle

The maximum number of connections that can remain idle in the pool, without extra ones being released (Old Default: 20) (New Default: 50)

db.pool.min.idle

The minimum number of idle connections to maintain in the pool. Note: the behavior differs by pool type: DBCP2: the eviction thread creates new connections to keep the idle count at or above this value. HikariCP: when set to a positive value, HikariCP makes a best effort to maintain that many idle connections while the total pool size remains below db.pool.max.active. At 0 the pool is fully elastic: it creates connections on demand and reclaims them once idle for db.pool.idle.timeout.millis setting. Note: For high-throughput sync workloads, HikariCP recommends setting this equal to db.pool.max.active to keep the pool warm and avoid connection-creation latency on every burst. Per HikariCP’s documentation, pairing this with an idleTimeout and maxLifetime shorter than the database’s own connection timeout is recommended to avoid stale-connection leaks. (Old Default: 5) (New Default: 50)

db.pool.type

Set the DB connection pool type. Options include: "dbcp2" for Apache DBCP2, and "hikari" for HikariCP. HikariCP is the default. HikariCP is included in the SymmetricDS distribution and requires no additional dependencies. (Old Default: dbcp2) (New Default: hikari)

purge.stats.retention.minutes

This is the retention for how long statistic data will be kept in the symmetric stats tables. Note that data will be purged only if the statistics flush job is enabled. The minimum value is 10,080 minutes (one week). (Old Default: 14400) (New Default: 21600)

purge.trigger.hist.retention.minutes

This is the retention time for how long an inactive table capture history will be retained. Inactive table capture histories will only be purged if they’re older than the earliest create_time in the data table and they don’t have a build reason of N. (Old Default: 86400) (New Default: 525600)

routing.collect.stats.unrouted

Enable to have the Refresh Data Create Time Metrics job collect unrouted row counts per channel, updating sym_node_host_channel_stats.data_unrouted and the rows.unrouted.channel.count metric. (Old Default: false) (New Default: true)