Overview

SymmetricDS Pro 3.18 release includes 32 features, 37 improvements, and 77 bug fixes.

Security Fixes

Issue Summary Severity

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

Performance Fixes

Issue Summary Severity

SYM-7534

Add Liveliness endpoint APIs for Kubernetes/Docker probe integration

High

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-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

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).

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

Improvements

3.18.0 (Pro)
SYM-7365 - Support AWS Aurora-specific PostgreSQL endpoints (PRO edition)
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-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

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

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

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: )

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)

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)

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)

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)

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: )

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)

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)