Timeplus Enterprise 3.3
Key Highlights
For a detailed tour of the new features in this release, see What's New in Timeplus Enterprise 3.3.
Key highlights of the Timeplus 3.3 release include:
- New backup and recovery capabilities: a stream tool for stream data recovery and backup/restore, sequence-aware backup and recovery controls, plus more resilient recovery paths with incremental commit replay and self-healing from torn WAL tails.
- Smarter cluster workload balancing: stream-shard leader rebalancing and a reliable workload rebalancer for materialized views, with new
SYSTEM TRANSFER SCHED MATERIALIZED VIEW/SYSTEM REBALANCE SCHED MATERIALIZED VIEWScommands and configurable scheduling policies. - Major Python UDF upgrades: embedded CPython migrated to 3.14 free-threaded with improved observability, UDF init hooks via SETTINGS, and automatic package reconciliation from S3-hosted requirements.txt.
- Faster and leaner startup and recovery: lazy-loaded primary key index to bound startup memory, memory-pressure interventions to prevent materialized-view reboot recovery storms, and containment of single-table startup failures.
- Streaming SQL enhancements: streaming LEFT ANTI JOIN,
SHUFFLE BYpropagation through CTE/subquery boundaries, shard pruning for IN-subqueries, and a new offsets-only checkpoint mode. - Broad stability and correctness hardening across Raft replication, checkpoints, mutable streams, Kafka sources, and memory accounting.
Supported OS
| Deployment Type | OS |
|---|---|
| Linux bare metal | x64 or ARM chips: Ubuntu 20.04+, RHEL 8+, Fedora 35+, Amazon Linux 2023 |
| Mac bare metal | Intel or Apple chips: macOS 14, macOS 15 |
| Kubernetes | Kubernetes 1.25+, with Helm 3.12+ |
Releases
We recommend using stable releases for production deployment. Engineering builds are available for testing and evaluation purposes.
3.3.4
Released on 10-28-2026. Installation options:
- For Linux or Mac users: Downloads
- For Docker users (not recommended for production):
docker run -p 8000:8000 docker.timeplus.com/timeplus/timeplus-enterprise:3.3.4 - For Kubernetes users:
helm install timeplus/timeplus-enterprise --version 13.0.8
Component versions:
- timeplusd 3.3.4
- timeplus_appserver 3.3.1
- timeplus_connector 3.1.0
- timeplus cli 3.0.0
- timeplus byoc 1.0.1-rc.2
Changelog
This release consolidates timeplusd changes introduced since 3.3.3. For changes already published in 3.3.3, see the 3.3.3 changelog below.
The 3.4.1 release predates several of the changes listed below, for example the Raft snapshot epoch fix (#12432) and Protobuf schema references with schema_message_name (#12479), so moving from 3.3.4 to 3.4.1 loses those changes. Before moving from 3.3.4 to a 3.4.x release, check that the changelog of that release lists the entries you rely on.
Features and Enhancements
- Kafka external streams with schema registry: support Protobuf schemas that import other schemas (references), and add two new settings —
schema_message_nameto pick which top-level message the stream's columns are inferred from, andconsume_schema_strategy(single/all/raw) to control how messages with different schema IDs are handled (#12479). consume_schema_strategy='single'now accepts every registered version of the stream's subject, so frames written before a compatible schema evolution stay readable (#12497).- With
consume_schema_strategy='single', a Protobuf message of a different top-level message type that shares the stream's schema ID is skipped instead of failing the read withNO_COLUMNS_SERIALIZED_TO_PROTOBUF_FIELDS; the stream's message is chosen byschema_message_nameand defaults to the first message of the schema (#12487, #12489, ported in #12491).SELECT count()on a schema-registry Kafka stream that resolves tosinglealso applies this filter instead of returning the raw number of Kafka messages (#12488, #12490, ported in #12491). - When
consume_schema_strategyis not set, its default now followssubject_name_strategy:'all'forTopicNameStrategy(or whensubject_name_strategyis not set), and'single'forRecordNameStrategy,TopicRecordNameStrategyand custom strategies (#12502, #12500). An explicit value always wins, and the resolved default is not stored in the stream DDL. Upgrade notes from 3.3.3:- Avro streams: no change. Streams using
RecordNameStrategy/TopicRecordNameStrategystill consume only the record type ofschema_subject_name, and streams usingTopicNameStrategystill consume every message. - Protobuf streams using
RecordNameStrategy/TopicRecordNameStrategy: 3.3.3 consumed every message of the topic regardless of its schema; 3.3.4 consumes only the messages of the selected subject (and of the message chosen byschema_message_name) and silently skips the rest. To keep the 3.3.3 behavior, setconsume_schema_strategy = 'all'. - A changed
consume_schema_strategy(including afterALTER STREAM ... MODIFY SETTING) is applied when the stream reloads, e.g. after a server restart. - Downgrade: streams that set
consume_schema_strategyexplicitly cannot be loaded by 3.3.3 (unknown setting). Streams that rely on the default can.
- Avro streams: no change. Streams using
- Merge TTL-expired parts before moving them to a no-merge volume (e.g. S3 cold tier), so they land as fewer, larger parts (#12269). A new stream setting
ttl_move_grace_secondsadditionally holds freshly written lone parts on the local volume so late batches can still merge before the move (#12360); its default is 1 hour (#12493). - Apply merge selector limits (
max_bytes_to_merge_at_max_space_in_pool,max_parts_to_merge_at_once) toOPTIMIZE STREAM ... PARTITION pwithoutFINAL; it now triggers one bounded merge per call instead of merging the whole partition, and compactsprefer_not_to_mergevolumes (#12367). - Reduce default system log retention and disable
log_query_threadsby default (#12441). The new retention is 3 days fortrace_log, 7 days forquery_thread_log, 14 days forpart_logand 7 days forstream_metric_log, andlog_query_threadsnow defaults tofalse. On the first start after the upgrade, the existingtrace_log,query_thread_logandpart_logtables (whose definition changed) are renamed to<name>_Nand kept rather than dropped, so their disk space is not reclaimed until you drop the renamed tables;stream_metric_logis dropped and re-created with the new TTL. Impact: with the old defaults, system log tables could consume most of a node's local disk. The same change shipped in 2.8.49 as #12440, see the 2.8.21 release notes (timeplusd 2.8.49).
Bug Fixes
- Stamp Raft snapshots with the committed entry's epoch instead of the election epoch (#12432). Impact: a replica that installed a snapshot right after a leader election could get permanently stuck, with the leader resending the same batches to it forever (up to hundreds of MB/s of node-to-node traffic); restarting did not help.
- Wait for the shard leader before proposing a write instead of letting Raft drop it (#12431). Impact:
CREATE STREAM ... AS SELECTon a multi-node cluster could lose its fill withINGEST_TIMEOUTand leave the new stream empty; any write landing during a Raft election blocked for the fullinsert_timeout_msand then failed. - Rewind the snapshot to sn 0 when the recipient's historical store is empty (#12456). Impact: a replica that lost both its NativeLog and historical store (e.g. a fresh disk or wiped PVC) rejected the catch-up snapshot and stayed at 0 rows forever.
- Fix
Unstable::trimerasing a single Raft log entry instead of the tail (#12429). Impact:SYSTEM RECOVER STREAMcould leave a hole in the unstable Raft log. - Fix append stream JOIN
versioned_kvdropping left rows while the joined right key is being updated (#12439). Impact:INNER JOINsilently lost whole left chunks;LEFT JOINemitted them with default right values. - Keep a re-created stream's execution assignment when the old stream of the same name is removed (#12465). Impact: after dropping and re-creating a scheduled materialized view under the same name, a node could silently reject later assignments, leaving the MV running nowhere (status
Unknown) or running twice. - Hide TTL-expired mutable stream entries on read and keep internal metadata out of TTL (#12473). Impact: on mutable streams with
ttl_seconds, half-expired rows could fail scans withLOGICAL_ERRORor return contradictory point-lookup results; TTL compaction could also drop internal metadata, so columns added byALTERread back empty after a restart, and re-added indexes returned nothing. Expired rows now disappear from reads as soon as they expire instead of at the next compaction. - Fill
CREATE STREAM AS SELECTwith an explicit column list (#12481). Impact: the fill insert could fail because the auto-added_tp_time/_tp_sncolumns made the target wider than the SELECT header; also fixed a crash path whenCREATE MUTABLE STREAM AS SELECTreads fromtable(x).
Known issues
CREATE EXTERNAL STREAMwithout a column list crashestimeplusdwhen the Protobuf schema has a recursive message type, includinggoogle/protobuf/struct.proto, so declare the columns explicitly (#12501).- A materialized view that groups a mutable stream and filters it with
WHEREoverwrites a group's aggregate (sum,avg,min,max) withNULLwhen an update makes the last row of the group stop matching, so move the condition into the aggregate, for examplesum(if(st = 1, v, 0))(#12132). - A streaming join of an append-only stream with a changing right side (
versioned_kv,changelog_kvor anEMIT CHANGELOGsubquery) can silently lose left rows while a right key is updated, so usejoin_algorithm='hash'instead ofparallel_hash(the other cases have no workaround yet) (#12443, #12444, #12445, #12447, #12450). - A follower replica can stay in the
Snapshotstate after a node restart or a failed Raft snapshot transfer, and restarting the node or changing the leader may clear it, otherwise contact Timeplus support (#12504, #12163, #12164). - A JavaScript aggregate function with a throwing property getter stops
timeplusdonCREATE, and every Python UDFCREATEkeeps a module in memory until restart, so avoid untrusted source and repeated Python UDF creation on a production node (#12329, #12330). - The Iceberg sink cannot write to Amazon S3 Tables, and time travel, partition transforms, row-level deletes, ORC or Avro data files, and
UPDATE,DELETEandMERGEare not supported (#12379, #12362). - Merges and mutations on very wide streams on S3 disks can run out of memory, so set tier-move TTLs to hours or days instead of minutes and leave memory headroom in
max_server_memory_usage(#12246, #12401, #12044). - A materialized view with
high_availability_model='scheduled'can run on two nodes after a failover and write duplicated output, and there is no workaround yet (#12458). - On mutable streams with
coalesced = true, a point lookup of only never-written column families returns no row, a partial update does not refresh thettl_secondsof the other column families, and a partial column-family insert is skipped, so write all columns of a column family together and do not combinecoalesced = truewithttl_seconds(#12475, #10514). - A query over changelog input with
EMIT ON UPDATE, periodic emit orEMIT CHANGELOGcan emit extra intermediate rows, such ascount() = 0, between the-1and+1of an update, so ignore them and use the final values (#12446, #12448, #12449). - A changelog
LEFT JOINwhere both sides track changes fails withMethod getInt is not supported for nullable(int8)whenjoin_use_nulls = 1, so keep the defaultjoin_use_nulls = 0(#12506). - A
directjoin loads the right side into memory and can use tens of GB, and thememory_usageof such a materialized view can be over-reported, so size nodes for the right side and use process memory (RSS) as the source of truth (#11113, #12408). - Some queries on large mutable streams are slow, such as
ORDER BYon indexed columns, largeINlists, and secondary-index predicates that skip the leading index columns, so keepINlists short and filter on the leading index columns (#11724, #10059, #11845, #11846, #11934, #11825). - DDL in a cluster takes effect asynchronously, so a statement right after
CREATEcan fail with a "does not exist" orRESOURCE_NOT_INITEDerror, and retrying after a short delay works (#8147, #9712, #12424). SELECT count()on a Kafka external stream returns too many rows for a compacted topic, so read the messages and count them instead (#4939).DROP STREAMis not blocked when aTASKreads the stream and leaves the task broken, so drop or change the task first (#11015).SHOW CREATE usersreturns the DDL of the users instead of a stream namedusers, so useSHOW CREATE STREAM users(#10194).- Correlated subqueries are not supported and fail with
Missing columns, so rewrite them as aJOIN(#205). changelog(tumble(...))is not supported, so applychangelog, then the window function, then dedup, thentable(#3062).- Row policies apply to historical queries only, not to streaming queries.
- A function in a view or subquery, such as
substring,json_extract_*or a UDF, can run more than once per row, so compute it once in the inner query and refer to the column (#1083).
3.3.3
Released on 09-29-2026. Installation options:
- For Linux or Mac users: Downloads
- For Docker users (not recommended for production):
docker run -p 8000:8000 docker.timeplus.com/timeplus/timeplus-enterprise:3.3.3 - For Kubernetes users:
helm install timeplus/timeplus-enterprise --version 13.0.7
Component versions:
- timeplusd 3.3.3
- timeplus_appserver 3.3.1
- timeplus_connector 3.1.0
- timeplus cli 3.0.0
- timeplus byoc 1.0.1-rc.2
Changelog
This release consolidates timeplusd changes introduced since 3.3.1. For changes already published in 3.3.1, see the 3.3.1 changelog below.
Features and Enhancements
- Harden timeplusd meta CLI and add offline database drop for outage remediation (#12300)
- Add partition-scoped backup and additive fill restore to the stream tool (#12331)
Bug Fixes
- Fix a Raft scheduler deadlock that occurred when an outbound send queue was full (#12418). Impact: could halt replication and leader election cluster-wide until restarted.
- Reject pausing a materialized view before its first pipeline build (#12328). Impact: a
SYSTEM PAUSE MATERIALIZED VIEWissued right afterCREATE MATERIALIZED VIEWcould block DDL processing on a node until it was restarted. Such a pause now fails withRESOURCE_NOT_INITEDand can be retried. - Recover trimmed Raft hard state from the durable checkpoint record (#12400). Impact: a replica could fatal-abort on every startup after a hard reset.
- Release historical parts once a streaming query has read them (#12375). Impact: outdated parts could not be deleted while the streaming query or materialized view that read them was running, growing disk usage.
- Retry a failed historical commit instead of wedging the committed sn (#12404). Impact: one failed commit could freeze a shard and grow disk usage indefinitely.
- Reset exec_mode for parallel-replica remote legs so materialized views over log external streams can start (#12373). Impact: such MVs could never start on a multi-node cluster.
- Fix checkpoint barrier loss in RemoteSource async-read path (#12326). Impact: an MV could silently get stuck at its first checkpoint epoch forever.
- Make NativeLog fetch honor the caller's byte budget (#12350). Impact: background polling could fetch up to 8192x more data than intended, risking OOM.
- Fix secondary index rebuild on mutable streams when the index key columns are a subset of the primary key (#12351). Impact:
ALTER STREAM ... ADD INDEXbackfilled existing rows under empty index keys, so index queries missed old rows and empty-string lookups returned bogus matches. - Make SYSTEM STOP MERGES/MOVES cover every shard of a multi-shard stream (#12304). Impact: the command silently affected only the first shard.
CREATE STORAGE POLICYnow rejects read-only and write-once (e.g.s3_plain) disks (#12377). Impact: TTL moves to such disks retried forever, causing massive redundant S3 writes. Existing storage policies are not re-validated on upgrade; if one uses a write-once disk, move it to a disk type that supports renames, such ass3.- Rewind idempotent keys when an inline historical commit fails (#12392). Impact: could cause permanent, silent data loss on commit failure.
- Fix null idempotent keys after a schema switch inside a historical commit batch (#12406). Impact: could crash the whole server (no data loss).
- Fix NULL handling in
arg_min/arg_maxover nullable columns (#12407). Impact: a NULL value could overwrite the aggregate result, and affected materialized views could fail checkpoint recovery withCORRUPTED_DATA. - Parse creation query AST every time on provisioner retry, so a retried CREATE no longer carries a stale UUID (#12325). Impact: a stale orphan directory could block cluster-wide schema creation.
- Fix PEM files not being flushed to disk for Kafka, HTTP and Splunk HEC external streams (#12335). Impact: the CA or private key file could be written empty, breaking TLS connections.
3.3.1
Released on 08-01-2026. Installation options:
- For Linux or Mac users: Downloads
- For Docker users (not recommended for production):
docker run -p 8000:8000 docker.timeplus.com/timeplus/timeplus-enterprise:3.3.1 - For Kubernetes users:
helm install timeplus/timeplus-enterprise --version 13.0.6
Component versions:
- timeplusd 3.3.1
- timeplus_appserver 3.3.1
- timeplus_connector 3.1.0
- timeplus cli 3.0.0
- timeplus byoc 1.0.1-rc.2
Changelog
This release consolidates all timeplusd changes from 3.2.11 through 3.3.1.
Features and Enhancements
- Add sequence-aware backup and recovery controls (#12274)
- Enable SYSTEM STOP and START MOVES (#12270)
- Add stream tool for stream data recovery and backup/restore (#12267)
- Tolerate corrupted checkpoint lease and keep it renewed during recovery (#12266)
- Contain single-table startup failure, raise broken-parts bytes threshold, shard-attributed load logs (#12264)
- Lazy-load primary key index to bound startup memory (#12250)
- Migrate embedded CPython to 3.14 free-threaded + FT observability (#11852)
- Memory-pressure interventions for materialized-view reboot recovery storm (#12219)
- MergeTree global merge settings (#12224)
- Propagate SHUFFLE BY through CTE/subquery boundaries (#12129)
- Stream-shard leader rebalancing — config + balancing core (#12204/#12215)
- Reliable workload rebalancer for Raft materialized views + manual trigger (#12204/#12205)
- Support Python UDF init hooks via SETTINGS (#12198)
- SYSTEM TRANSFER SCHED MATERIALIZED VIEW (#12189/#12201)
- SYSTEM REBALANCE SCHED MATERIALIZED VIEWS - manual rebalance trigger (#12200)
- Schedule policy (#12196)
- Reconcile Python UDF packages from S3-hosted requirements.txt (#12186/#12187)
- Throttle repeated Kafka broker outage warnings (#12191/#12194)
- Support flush hook in Python external stream sink (#12183/#12184)
- Refine merge settings (#12178)
- Prefer not to merge settings (#12161)
- Add offsets-only checkpoint mode (#11753)
- Enhance stall detection (#12074)
- Enable shard pruning for IN-subquery and literal tuple-IN (#12139)
- Support NATS NKey authentication (#12120)
- Support streaming LEFT ANTI JOIN (#12119)
- Support setting JWT and seed content in settings (#12116)
- Block mutable stream secondary index creation for unsupported key expressions (#12113)
- Refresh QueryScope per build to clear phantom memory_tracker amount (#12096)
- Unblock metric tick from S3 LIST + TTL cache historical-store size (#12052)
- Enable vertical merge for wide part (#12057)
Bug Fixes
- Decode pip output as UTF-8 instead of the locale encoding (#12293)
- Keep -1/+1 consecutive pair contiguous through the shard merge (#12234)
- Stage pip into the Python asset so package install works (#12285)
- Sync executor with upstream and back off merge selection after memory-limited failures (#12247)
- Clamp negative low_sn to 0 when logging processed_sn fallback (#12277)
- Fix SYSTEM STOP MERGES segfault on streams without local historical storage (#12268)
- Bound hydrated bytes parked in shared storage fetch batches (#12262)
- Fix silent data loss when Raft proposals are dropped during no-leader windows (#12260)
- Fix JS UDF dictionary getValue/batchGetValues missing-key handling (#12253)
- Fix stream recovery replay with incremental commits (#12251)
- Stop torn-tail recovery from inverting a loglet (#12238)
- Stop the historical-recovery OOM crash-loop at write, load, and recover (#12237)
- Gate retention on a real applied-SN (#12228)
- Rebind prefix-range slices after merge (#12230)
- Reduce default TTL of high-frequency metric logs (#12226)
- Override isReady() to gate materialized view builds on schema readiness (#12222)
- Check attributes existence before JSON extraction (#12216)
- Mitigate Protobuf map-entry issue for Confluent schema registry (#12211)
- Manual rebalance trigger: immediate task is not a scheduling failure (#12208)
- Deterministic per-stream tie-break to remove low-node-ID placement bias (#12207)
- Use the shard's storage when listing active parts in system.parts (#12192, #12193)
- Roll back torn WAL tail on partial write under ENOSPC (#12185)
- Throw bad_alloc on failed ByteVector allocation instead of NULL dereference (#12181)
- Suppress phantom changelog rows in multishard memory aggregation (#12162)
- Restore data_version on StoragePolicyDescriptor deserialize (#12170)
- Drop spurious "Profile counters are not set" warning (#12166)
- Clone inner_query and serialize lazy semantic init (#12152)
- EMIT ON UPDATE no longer drops updates when +1 partner is filtered to empty (#12126)
- Direct join honors nullable left keys (#12143)
- Enforce NAMED_COLLECTION access in settings merge (#12151)
- Fix DROP DATABASE CASCADE failure when alerts exist (#12130, #12158)
- Self-heal NativeLog replica from torn-WAL inconsistency instead of crash-looping (#12156)
- Restore min_size_to_keep floor for metadata and checkpoint logs (#12137)
- Make version_column + TTL safe (#11991)
- Cap delayed write streams for parallel-write disks (#12123)
- Background NativeLog commit no longer throws TOO_MANY_PARTS (#12112)
- Skip filter and expression fusion when child carries substream-aware stateful functions (#12111)
- Bump V8 and cherry-pick ARM64 64K-page fixes (#12105)
- Apply proposed librdkafka fix for improved Kafka stability (#12103)
- Fix Pulsar health check and ddl_index/named_collection issues (#12088)
- Fix mutable stream file descriptor leak (#12093)
- Align DNSResolver throw type with upstream (#12087)
- Fix incorrect alert dependency tracking behavior (#12080)
- Resolve Python interpreter symlinks recursively (#12081)
- Fix Kafka client race between shutdown() and read() (#12078)
- Fix mutable stream corruption after adding an index and rebooting (#12070)
- Probe builtin views via system.stream_shards (#12047)
- Retry on Poco::Exception in ReadBufferFromS3::nextImpl (#12041)
- Fix hanging issue when recreating Kafka consumer (#12038)
- Gate OTel external stream on USE_GRPC (#12032)
- Fix data race in getting watermark (#12031)