InfluxDB’s TSM (Time-Structured Merge) engine is a write-optimized storage engine that uses a log-structured merge-tree (LSM-tree) approach to store time-series data.

Imagine you’ve got a firehose of data, metrics streaming in constantly. InfluxDB needs to slurp all that up without breaking a sweat, and then let you query it back out fast. TSM is how it pulls off that trick. Instead of trying to update data in place like a traditional database (which is slow for writes and even slower for time-series where data is always appended), TSM writes everything to memory first, then flushes it out to disk in immutable files, and periodically merges these files in the background.

Here’s a peek at it in action. Let’s say we’re writing some temperature data:

curl -XPOST 'http://localhost:8086/write?db=mydb' -d 'temp,city=london value=15.2 1678886400'
curl -XPOST 'http://localhost:8086/write?db=mydb' -d 'temp,city=london value=15.5 1678886460'
curl -XPOST 'http://localhost:8086/write?db=mydb' -d 'temp,city=london value=15.3 1678886520'

When these writes come in, they first hit an in-memory buffer called the "write-ahead log" (WAL). This WAL is durable – if InfluxDB crashes, it can replay the WAL upon restart to recover any data that hadn’t yet been flushed to disk.

Once the in-memory buffer is full, or after a certain time interval, the data is flushed from memory into a "memtable" (another in-memory structure) and then written to disk as a new TSM file. These TSM files are immutable, meaning once written, they are never modified. This is key to TSM’s performance.

Let’s look at a snapshot of what a TSM file might represent. This isn’t a direct view you’d get from a command, but conceptually, it’s a sorted collection of data points for a given series (measurement, tag set, field key) within a time range.

A single TSM file might contain data like this (again, conceptual):

# Measurement: temp
# Tag Set: city=london
# Field Key: value

1678886400 15.2
1678886460 15.5
1678886520 15.3

InfluxDB writes these TSM files in levels. Level 0 contains the newest, un-merged data flushed from memory. As more data is written, Level 0 files accumulate. In the background, InfluxDB performs "compaction" processes. Compaction merges multiple TSM files from one level into new, larger TSM files in the next level. This process also de-duplicates data. If you write a point for a specific series at a specific timestamp twice, only the latest one will be kept.

The goal of compaction is to reduce the number of TSM files and to organize data more efficiently. Level 1 files might contain merged data from several Level 0 files, Level 2 from Level 1, and so on. Higher levels contain older, more aggregated data.

When you query data, InfluxDB consults these TSM files. It starts by looking at the most recent data in Level 0, then checks higher levels if necessary. For a given time range and series, it might need to read from multiple TSM files across different levels. The compaction process ensures that the number of files to check is kept manageable.

The core problem TSM solves is efficiently handling the high write throughput characteristic of time-series data while still providing fast read performance for range queries. By writing to memory and then to immutable files, it avoids the overhead of random I/O and in-place updates. The LSM-tree structure, with its levels and background compactions, is the mechanism that keeps the number of files on disk from exploding and ensures that reads don’t become prohibitively slow.

The actual TSM files are binary, but they are structured with an index at the beginning that maps series and time ranges to offsets within the file. This index is what allows InfluxDB to quickly locate the relevant data blocks for a query without scanning the entire file.

When a compaction occurs, InfluxDB reads data from several source TSM files, merges it (keeping the latest points for duplicate timestamps), and writes the result into new TSM files for the target level. This process is resource-intensive and can be configured to run with certain throttling parameters to avoid impacting query performance. The compaction settings in influxdb.conf control how aggressively this happens.

The next challenge you’ll likely encounter is understanding how InfluxDB handles downsampling and retention policies, which are built on top of this storage engine.

Want structured learning?

Take the full Influxdb course →