TigerData logo

Speed Without Sacrifice: 9000x Faster High Performance Ingestion, 42x Faster DELETES, Improved CAgg Updates and More in TimescaleDB 2.21

Speed Without Sacrifice: 9000x Faster High Performance Ingestion, 42x Faster DELETES, Improved CAgg Updates and More in TimescaleDB 2.21

We're thrilled to announce TimescaleDB 2.21, a release that continues our relentless pursuit of making Tiger Postgres the fastest PostgreSQL for time-series and real-time analytical workloads. Building on the foundational improvements of 2.20, this version delivers more performance enhancements and crucial advancements in usability, all while preserving the flexibility, full SQL capabilities, and rich ecosystem you expect from PostgreSQL.

At TigerData, our grand ambition is to build the fastest Postgres, driven by exponential data growth and sophisticated customer-facing apps that require real-time analytics and AI capabilities. To achieve this, we remain laser-focused on two core areas: performance and usability.

  • Performance: "Fastest Postgres" – Achieving unparalleled speed, scalability, and efficiency without sacrificing reliability or operational simplicity. This means enhancing the core engine for raw power, optimizing ingestion for high throughput, optimizing data for low-latency querying, and refining background processes for seamless operation.
  • Usability: "Zero-config Experience" – Simplifying the user journey from setup through advanced features. Our goal is an "automagic" setup for instant productivity, zero-config hypertables by default, and seamless adoption of features by reducing the learning curve.

TimescaleDB 2.21 continues to build on these themes, further improving performance while enhancing the experience for our users. Get ready for impressive speed-ups and powerful enhancements that help you move faster and scale smarter.

TL;DR

TimescaleDB 2.21 makes PostgreSQL for demanding applications and real-time analytics even faster and simpler to use. Key highlights include:

  • Direct to Columnstore (Tech Preview): A revolutionary new approach to ingestion that moves data directly into the columnstore at insert time, allowing for sustained rates over 5M records per second with bursts up to 100M records per second in tests. This is a journey we're embarking on, and we're seeking design partners!
  • Faster Data Management:
    • UPSERTs into the columnstore are now 2x faster for heavily constrained tables, building on the 10x improvement from 2.20.
    • DELETEs of non-segmentby columns are 42x faster, significantly reducing I/O and bloat.
    • Reduced bloat after recompression, freeing up disk space and preserving concurrent access.
  • Smarter Continuous Aggregates (CAggs):
    • Parallel refresh policies allow multiple CAggs to update concurrently without conflicts.
    • Batched refreshes are now enabled by default, breaking large refreshes into smaller, more efficient chunks.
  • Complete Chunk Management: Full support for splitting compressed chunks, complementing our existing merge capabilities.
  • Best Practices: Changes to our 25% rule for chunk sizing

With the TL;DR out of the way, let's deep-dive into everything 2.21 has to offer!

High Performance Ingestion: Introducing Direct to Columnstore (Tech Preview)

For high-throughput, real-time analytical applications such as observability platforms, IoT systems, or financial data pipelines, efficient ingestion is critical. These workloads generate massive volumes of data that need to be stored and queried with minimal delay. To support these use cases, TimescaleDB 2.21 introduces a new ingestion path: Direct to Columnstore. This feature allows data to be ingested directly into the optimized columnar format, reducing unnecessary I/O and enabling significantly higher throughput.

How does it work?

In most databases, including PostgreSQL, ingestion performance is typically limited by I/O throughput. Each insert operation writes to multiple places on disk: the heap (rowstore), indexes, and the write-ahead log (WAL). At high ingest rates, this disk activity becomes a major bottleneck. By default, TimescaleDB’s columnstore required data to be ingested into the rowstore first, then later compressed and moved to the columnstore by a background policy. This two-step process requires additional I/O overhead.

Direct-to-columnstore eliminates that extra step. Instead of writing to the rowstore and compressing later, data is immediately written to the optimized columnstore during ingestion. This bypasses redundant I/O and index maintenance. 

Why are we doing this? 

Our goal is to make ingestion faster so users can scale to higher ingest rates without hitting I/O limits. Direct-to-columnstore reduces the disk activity required during ingestion, which lowers system overhead and simplifies operations. In our internal testing, this approach reduced I/O by up to 80 percent and enabled ingestion rates up to 9,000 times faster than the default path, with tested bursts reaching 100 million rows per second. By making ingestion CPU-bound instead of I/O-bound, it allows users to handle larger volumes of real-time data with less hardware and fewer tuning requirements, all while still benefiting from the compression and query performance advantages of columnar storage.

Key benefits:

  • Dramatic Ingestion Speed: It offers revolutionary increases in ingestion performance. In our tests, we've observed bursts up to 100 million records per second! The operation becomes CPU-bound, meaning performance continues to scale with available CPU capacity.
  • Reduced I/O Overhead: By bypassing the traditional rowstore and dense indexing that occurs during that process, disk I/O is significantly reduced, leading to more efficient data ingestion.
  • Simplified Management: Eliminating the need for separate, post-ingestion compression jobs reduces CPU and memory usage, operational complexity and system overhead.
  • Optimal Storage & Query Performance: Data lands directly in the optimized columnar format, inherently improving storage efficiency and subsequent query performance on freshly ingested data.
  • Enhanced Analytics: Compressed columnar storage combined with vectorized execution accelerates queries and delivers faster insights.
image
Figure 1: Conceptual diagram of Direct-to-Columnstore, showing data bypassing the traditional rowstore and writing directly to the columnstore for streamlined ingestion.

A journey and a tech preview

We believe these improvements to ingestion will be a game-changer for high throughput TimescaleDB users, but it's important to note that within 2.21 it’s a tech preview feature. This means it's a significant step in an ongoing journey that will take time to fully mature for all use cases.

Current limitations for 2.21:

  • COPY Support Only: There is only support for COPY operations. Support for INSERT statements is planned for an upcoming release.
  • Data Ordering: Optimal performance requires strict data ordering and batching. Without this, additional maintenance tasks are needed to reorder unordered data, which are not yet fully optimized.
  • CDC: This functionality will allow compressing data during ingestion in memory. This means no WAL records will need to be written for individual records but only for the compressed batches.
  • Potential for Misuse: There's an advanced configuration flag (GUC) timescaledb.enable_direct_compress_copy_client_sorted (default: off) that, if incorrectly set (e.g., guaranteeing data order when it's not actually ordered), can lead to inaccurate query results. We advise users to consult with our team on the best approaches to leverage this feature.  
  • CAggs - Continuous aggregates are currently unsupported when using direct-to-columnstore writes because this path bypasses the invalidation log that CAggs rely on to detect changes. Support for CAggs will be added once columnstore inserts integrate with the invalidation framework in a future release.
  • Constraints & Triggers - Currently, there is no support for unique constraints or triggers, so they cannot enforce row-level uniqueness or run custom trigger logic until a later version

Getting started with direct-to-columnstore

It only takes a few steps to start ingesting directly into the columnstore. Below is a simple example using CREATE TABLE, enabling the feature with a GUC, and loading data using COPY. For additional details check out our documentation and we will be launching a blog article that will dive much deeper into this topic.

tsdb=> CREATE TABLE t(time timestamptz, device text, value float) WITH (tsdb.hypertable,tsdb.partition_column='time');
CREATE TABLE
Time: 17.940 ms

tsdb=> SET timescaledb.enable_direct_compress_copy;
SET
Time: 1.103 ms

-- binary format will achieve highest insert rate
-- but csv and text format are supported as well
tsdb=> COPY t FROM '/tmp/t.binary' WITH (format binary);
COPY 10000000
Time: 0.730 ms

We are actively seeking design partners to test this feature in real-world environments. Ideal partners are those experiencing ingestion bottlenecks, have strong control over their data pipelines (can reliably batch and order data consistently), and require real-time or very fast access to freshly ingested data. If this sounds like you, please reach out to our team!

Enhanced Data Management & Columnar Efficiency

TimescaleDB 2.21 delivers significant improvements to how you manage and optimize your data within the columnstore, making common operations faster and more efficient.

Faster UPSERTs into the columnstore

Backfilling or updating data into compressed columnstore chunks has been a pain point for some users. TimescaleDB 2.20 brought a massive 10x improvement, and 2.21 continues this momentum. For heavily constrained UPSERT or ON CONFLICT operations, performance is now 2x times faster than in 2.20.

Consider a worst-case scenario backfill of 3,000 records where every record conflicts with an existing unique constraint:

INSERT INTO uk_ts_comp_table
	SELECT * FROM insert_sample on conflict (uk,ts) do nothing;

TimescaleDB 2.19: ~17 seconds
TimescaleDB 2.20: ~1.7 seconds
TimescaleDB 2.21:
~.7 seconds (a 20x improvement!)

image
Figure 2: Backfill UPSERT performance comparison for 3,000 rows with conflicts on a unique constraint, showing significant speedups in 2.20 and further improvements in 2.21.

This brings UPSERT performance for append-only workloads almost on par with rowstore chunks, truly delivering speed without sacrifice.

Improved DELETEs of non-segmented columns

Deleting records from non-segmentby columns previously required decompressing batches to validate conditions, an expensive operation that also generated bloat. TimescaleDB 2.21 introduces a new optimization that validates if a whole batch can be deleted at once based on the given conditions.

This results in:

  • Much faster operations: Benchmarks show a 42 times faster DELETE compared to 2.20 in certain scenarios.
  • Less I/O and less locking: No need to decompress and recompress a batch, generating less bloat.
  • Benefits for CAggs: Continuous Aggregates that use the columnstore will benefit significantly during refreshes, which frequently delete batches.
image
Figure 3: DELETE operation performance comparison, demonstrating a 42x speedup in TimescaleDB 2.21 compared to 2.20.3.

Reduced bloat after recompression

With recent architectural changes to improve read/write during recompression, a trade-off was made to use DELETE over TRUNCATE, which could lead to bloat (deleted records occupying storage space until garbage collected). In 2.21, we implemented a smarter way to reduce this bloat. Customers will notice this improvement after larger recompression operations, resulting in less disk usage and more efficient storage.

Split columnstore chunks

TimescaleDB 2.20 introduced the ability to split rowstore chunks. In 2.21, we completed this feature by adding support for splitting columnstore chunks. This provides full flexibility to manage your data, complementing our existing merge capabilities for both columnstore and rowstore data. This is particularly useful for fixing chunk interval configuration mistakes or managing very large chunks.

Continuous Aggregates: Smarter, Faster Analytics

Continuous Aggregates (CAggs) are a cornerstone of managing and querying large time-series datasets efficiently. TimescaleDB 2.21 introduces more flexibility and power to how you define and manage them, making them even more robust for real-time analytics.

Concurrent refresh policies

Previously, refreshing Continuous Aggregates could involve locking the materialization hypertable, preventing concurrent executions. This often led to customers creating complex workarounds when they had multiple CAggs against the same hypertable.

TimescaleDB 2.21 lifts this limitation by introducing an improved locking approach and smart decision logic. Now, multiple refresh policies can run concurrently, refreshing only ranges that are not overlapping with other running policies.

For example, in a multi-tenant application, a new customer onboarding might involve loading both historic data and real-time data. With parallel refresh policies, separate policies for historic and real-time data can run concurrently, ensuring faster materialization and improved data availability without conflicts. This is a significant win for use cases requiring faster materialization. The example below illustrates this.

-- Refresh policy for recent data (last 24 h)
SELECT add_continuous_aggregate_policy('conditions_summary_daily',
  start_offset => INTERVAL '1 day',
  end_offset => INTERVAL '1 h',
  schedule_interval => INTERVAL '1 h');

---- Refresh policy for historical data (older than 24 h)
SELECT add_continuous_aggregate_policy('conditions_summary_daily',
  start_offset => NULL
  end_offset => INTERVAL '1 day',
  schedule_interval => INTERVAL '1 hour');

Batched refreshes (now default)

Starting in 2.19 you could opt-in to batched refreshes, which slice a continuous-aggregate refresh into smaller pieces so results appear sooner and large jobs don’t monopolize CPU, memory, or I/O. In 2.21 this is now on by default:

buckets_per_batch = 1

How it works: each batch processes one time bucket. Raising the value refreshes more buckets per batch but uses more resources. Lowering it keeps resource usage minimal at the cost of more batches.

max_batches_per_execution = 0 (unlimited).

How it works: controls how many batches a single policy run will execute. Setting a positive number caps work per run; zero lets the job finish all pending batches.

With these defaults, even very large Continuous Aggregates refresh in bite-sized chunks, keeping the system responsive while making new data visible quickly. The next step is to have TimescaleDB pick these values automatically based on the size of the refresh window and recent workload patterns.

Best Practices & Accelerating Delivery

Beyond the features, we are accelerating our release schedule and have new recommendations on best practices. 

Change of the 25% rule

The "25% rule" for chunk sizing, which previously advised setting chunk size to approximately 25% of system memory based on total chunk size, is outdated. We've evolved this metric. We are now advising users to reference the index size on the chunks with reference to 25% of memory for uncompressed chunks. This change is already reflected in our documentation, and the Tiger Cloud Console now displays index size alongside chunk size for your reference. This ensures more accurate guidance for optimal memory utilization and query performance. You can find more details in our updated documentation.

New release cadence

To accelerate our pace of innovation and deliver value to you faster, TimescaleDB will be changing its release cadence. Starting with the 2.22 release in September, we will shift from an 8-week minor release cycle to a 4-week minor release cycle, with one planned patch release two weeks after each minor release. This "always be launching" approach allows us to get new features into your hands more quickly..

PostgreSQL version updates

As announced with TimescaleDB 2.19.0, version 2.20 dropped support for PostgreSQL 14. TimescaleDB 2.21 is compatible with PostgreSQL 15, 16, and 17. We recommend users aim for the latest PostgreSQL versions to benefit from their own performance and security enhancements.

For Tiger Cloud customers still on PostgreSQL 13 or 14, a forced upgrade to PostgreSQL 15+ is planned for mid-September. Please plan your PostgreSQL upgrades accordingly to take advantage of the latest TimescaleDB features. 

Conclusion: Upgrade to TimescaleDB 2.21 Today!

TimescaleDB 2.21 marks another significant leap forward, reinforcing its position as the fastest PostgreSQL for time-series and real-time analytics workloads. We've delivered substantial speed improvements for ingestion, data management, and continuous aggregates, all while maintaining the robust capabilities, full SQL, and developer experience you expect from PostgreSQL.

For Tiger Cloud users on PostgreSQL 15 and above, these enhancements are already live and available. Self-hosted users can upgrade now to explore these benefits firsthand.

Check out our release notes for a full list of improvements and bug fixes. As always, we welcome your feedback in our Community Forum or on GitHub.


About the author:

Brandon Purcell is a Staff Product Manager at TigerData, where he leads the Database team with a focus on delivering a world-class experience out of the box for developers using the Tiger Postgres platform, both in the cloud and open source. His work centers on improving core database functionality and helping customers unlock value from their time-series, event, and real-time analytics workloads.

Prior to joining TigerData, Brandon was responsible for leading Product Development within the Analytics Product Development group at Insurity, overseeing Geospatial, Predictive, and Data products. He was also a co-founder and CTO of SpatialKey, a geospatial analytics platform acquired by Insurity in 2020. At SpatialKey, he guided the company’s evolution from a general-purpose geospatial tool to a vertically focused insurance analytics product supporting underwriting, event response, and portfolio management.

With over two decades of experience leading globally distributed teams, Brandon’s career began at Macromedia and Adobe, where he supported mobile and developer tooling programs. Earlier still, he served as a Communications Officer in the U.S. Army, where he authored TACWEB, one of the Army’s first web-based command and control systems. Brandon holds a degree in Electrical Engineering from Southern Illinois University and lives in upstate New York.

Date published

Aug 06, 2025

Share

Subscribe to the TigerData Newsletter

By submitting you acknowledge TigerData's Privacy Policy.