Most MongoDB replica sets start small. The working set fits in the WiredTiger cache, reads come from memory, and nobody thinks about disks. Then the data keeps growing. Orders, events and logs pile up for years, and one day the collection is ten times the size of the cache.
From that point every read of a document that is not cached is a read from disk. Latency follows the disk, not the query. On the cluster I tested below, a read p95 of 70 ms was not a bad index, it was a disk at its IOPS limit.
The usual answer is sharding. It works, but it is a big step and very costly: a shard key you cannot easily change, mongos routers, config servers, balancing, and queries that need the shard key to stay fast. For a team whose real problem is “most reads are for recent data, and old data is in the way“, that is a lot of machinery.
The question I wanted to answer: can you keep the replica set you have, and put the recent data somewhere fast in front of it, without changing the application?
Thermocline is storage tiering for MongoDB. The cluster you have becomes the archive, exactly as it is. A new, smaller replica set in front of it holds the recent documents. The application connects to a proxy instead of the old cluster.
The application talks to one proxy; age decides which tier holds a document

Four pieces keep the two tiers consistent:
Nothing is loaded by hand. The fast tier starts empty and fills from the warmer and from the documents that traffic requests.
The test cluster ran on Hetzner Cloud. It is built to be the case above, not a flattering one:
Three mixes:
Every run was measured twice: the existing cluster alone, and the same cluster behind Thermocline. Same MongoDB release on both tiers, same caps, same client.
The same capped cluster did 1.6x to 5.2x more operations per second behind Thermocline, with 0 operations refused in any run.

The more the traffic is about recent data, the bigger the gain: the concentrated mix went from 4,447 to 23,340 operations per second. Its read latency fell with it, from a p95 of 86 ms to 6 ms and a p99 of 92 ms to 8 ms.
At the same load, reads stop waiting for the disk. I asked both sides for 6,165 operations per second on the store mix, the old cluster’s maximum. Alone, it delivered 6,086 with a read p95 of 70.5 ms. Behind Thermocline it delivered 6,156 and 6,159 in two runs, with a read p95 of 2.8 ms and 2.1 ms. The p99 moved between 7 and 27 ms from one run to the next, against 81 ms alone. The archive’s disk did 1,838 reads per second instead of 2,704.

Adoption starts from an empty fast tier. The realistic first day is a fast tier with nothing in it, filled by traffic and the warmer. Over 30 minutes of the store mix, flat out, the pair averaged 8,221 operations per second, 42% more than the old cluster alone with cold caches (5,803). It passed the old cluster’s number after 100 seconds, averaged 6,417 in the first five minutes and 9,146 in the last five, and copied 271,271 documents up from the archive on the way.

The gain comes from reads that the fast tier can answer. Everything else still lands on the existing cluster, and that sets the limits:
The gain depends on the mix: 1.6x on the store mix and 5.2x when activity is concentrated on recent data, on the same hardware. Measure your own case before believing mine.
A replica set that outgrew its memory usually gets one of two answers: bigger machines, or sharding. Both cost money and time, and sharding changes how the application has to be written. Tiering is a third option for the common case where most of the traffic is about recent data: keep the cluster you have as the archive, put a small fast cluster in front of it, and let age decide where each document lives.
The code is on GitHub at github.com/zelmario/thermocline, under the Apache 2.0 license, and its README explains how to run it.
If you have a replica set in this situation, I would like to hear about it, and even more about a workload where this does not work. Issues and pull requests are welcome.
Note: This is a proof of concept.
Thermocline is a POC I built to answer one question: can a small fast cluster in front of an existing replica set take the load off it, without changing the application, so that sharding or bigger servers are not the only way out?
The results say it can be a viable alternative for the right workload. The numbers come from a test cluster. It has not run in production yet.
Resources
RELATED POSTS