How SHOPLINE Saves 40% Space in Main Database
Data tiering in practice: a guide to Hot and Cold data storage

Recently, our organization has been driving a technical transformation where we are tiering data and archiving so-called “cold data” to less costly storage.
Typically, a system must originally use a database that is both fast to access and capable of supporting complex queries, i.e. a database for OLTP scenarios. Inevitably, the unit cost of such a database must be high, which means the more data stored, the more expensive it is, and exponentially so.
Therefore, it is valuable to move some infrequently used data out of the original OLTP database and store it in a lower cost “place”. This process is called data tiering or data archiving.
This “place” is sacrificing many features for price advantages, such as poor access performance. Furthermore, the archived data may never be modified again, depending on requirements, and may only be available for viewing.

The diagram above provides a clear overview.
Depending on the use case, the application may still have access to all the data, and there may be differences in usage depending on the scenario. However, at the data layer the data has actually been split into two different stores, one fast and costly, the other slow and inexpensive.
Business-driven or Tech-driven?
Do you feel that this organizational transformation is a tech-driven or a business-driven project?
To be honest, this would be a business-driven project. The reason is simple: the act of archiving cold data has a significant impact on the user experience.
When you’re a user of a system, let’s say a bank user, would you want to see all past transactions or just three months of transactions? Undoubtedly, I’m sure you’d want to see all of them, and they’d have to be complete, including time, recipients, amounts, and even notes.
Suppose your bank originally disclosed all the records of the past years, until one day, the bank realized that the cost of data storage is too high and need to archive the transaction records of three months ago, how would you feel?
Unhappy, maybe even quit, right? Yes, that’s why data archiving is a business-driven project.
What is Cold Data?
So, here comes another question. How do we define cold data? I mean what data we have to archive in order to have as little impact on the user experience as possible.
To be able to answer this question, we first need to have observability.
- the distribution of data, i.e., the volume of data as a percentage
- the time distribution of the data
- how users use the data
- the time distribution of the data being used
With these metrics we can further analyze which tables need to be tiered, and we can also identify the timing of the tiering.
I believe that the first and second points should be fairly simple, but the critical third and fourth points are almost impossible to obtain without having them built into the system in advance.
So what should we do?
Fortunately, we still have one more tactic, which is the fake door test.
Since we can’t know the context in which the user is using the data, we can make some hypotheses and verify them by making small changes to the application.
For example, our UI can see all bank transactions, but we want to hide transactions from six months ago. We’re not sure if six months is a good time condition, so we’ll just mask the six months ago data on the UI instead of physically archiving it.
In addition to masking, we also wanted to know if this would affect the user experience, so we added a Load More button to record user actions. This way, we know how many users need those six-month old records, and how often they need them.
Moreover, we can take six months as a unit to evaluate how often the data from a year ago or even a year and a half ago is used, so that we can adjust the time hypothesis we set.
Eventually, we can know what is a reasonable cold data from the results of the fake door test.
How to Cold Down
When we have set the scope of cold data, we then need to consider how that cold data will be accessed.
Once again, this is still not a purely tech-driven issue, but is actually determined by business requirements.
Although we all know that the low price of cold data comes at the expense of accessibility, how much impact on the user story will significantly determine our decision.
Here are a few considerations, so let’s discuss them one by one.
User scenario
Once we have clearly distinguished between hot data and cold data, is there a difference in the usage of these two types of data?
Usage here is not about the impact of non-functional requirements such as slow responses, but rather whether we would treat cold data and hot data in the same user scenario.
Continuing with the bank transactions example, let’s assume that transactions older than six months are considered cold.
Here are a few questions to think about.
- Should records older than 6 months be able to be displayed seamlessly on the list page?
- Should records older than 6 months be able to be displayed via “Load More”?
- Can we allow the editing of notes for transactions older than 6 months?
- Can we not show records older than 6 months at all?
From top to bottom, we have higher and higher impact on the user story, e.g. in point 3 we allow cold data to be read-only, and even more so in point 4 we allow cold data to be completely inaccessible.
We can know that the more forward options cost more.
Functional limitations
In the user scenarios, we consider whether the cold data is visible and modifiable, but this is not enough.
In the business logic, it is not only about the availability of the records, but also about the aggregation and other operations.
For example, the transaction records can be summed up by month to show the consumption trend, and the consumption percentage can be categorized by transaction targets. Not to mention, there are also some cross-domain data computation requirements.
If we store all the cold data in the form of csv in the object storage system, it is true that we can get a very low storage cost, but all the computing requirements must be parsed out of the whole csv, which will dramatically increase the cost of use.
Therefore, how to balance the cost of storage and the cost of use in terms of functionality is also an important consideration.
Existing technical stacks and data structures
Once we have reached a conclusion on the first two points, the only thing left to do is to fulfill the business requirements within the existing architecture.
Why is this also a critical consideration?
Let’s use a case study to illustrate.
Suppose we decide to treat half a year as a hot and cold junction, and the cold data should be able to be displayed seamlessly on the list page, but it cannot be written to, only read, and all the business logic should be the same as before.
Would this be a harsh condition? It depends. If we’re using Elasticsearch as our main database and defining indexes in terms of time series, then this condition is a piece of cake.
I’ve explained the mechanism and concepts of Elasticsearch’s Index Lifecycle Management, aka ILM. Therefore, it is quite easy to fulfill such business requirements.
However, if our main database is MySQL, then it would take much more effort to accomplish the same business requirement than using Elasticsearch.
To sum up, how to archive cold data depends a lot on the business requirements, but also on the existing technical stack and implementation.
Common Approaches
Let’s list some common data tiering technical options and explain the scenarios where they apply using a few of the mentioned business requirements.
For the sake of simplicity, let’s summarize the requirements. Let’s start with the business requirements and focus on the following three.
- Readable
- Writable
- Aggregatable
In addition to the functional requirements for business, there are also non-functional requirements, so let’s focus on the three core requirements.
- Storage Cost
- Computing Cost
- Access Latency
In addition, I would like to add a key non-functional requirement.
- Implementation Complexity
Native support
As mentioned in the previous section, when using Elasticsearch’s ILM, there is a simple data tiering architecture when dealing with time-series data.

- Readable (v)
- Writable (x)
- Aggregatable (v)
With Elasticsearch’s ILM, it is possible to reduce storage costs by using nodes with poor hardware specifications as cold data nodes, even though the cost is still higher than object storage.
However, because Elasticsearch can keep indexes, query performance will normally reflect the hardware specification savings, and the worse the hardware specification, the worse the query performance will be. Fortunately, this performance loss is still much better than the performance of object storage.
- Storage Cost (high)
- Computing Cost (low)
- Access Latency (low)
- Implementation Complexity (low)
In fact, if using a database with built-in lifecycle management such as Elasticsearch, then similar characteristics will be available.
Application sharding
It is because of Elasticsearch’s built-in ILM that data tiering can be achieved with little or no modification to the application’s implementation. However, applications that do not use Elasticsearch as their main database are not so lucky, and they have to implement their own sharding logic in the application.
The first step is to prepare two homogeneous databases, one with a high specification for hot data and the other with a low specification.

The application determines which database to obtain data from based on the query criteria, and if necessary, it must also do the hot data and cold data join.
The creation of cold data is usually handled by a background Extract-Transform-Load (ETL) process.
- Readable (v)
- Writable (v)
- Aggregatable (v)
Since there are two homogeneous databases, the impact of the usage scenario can be minimized and the ability to write cold data is also available.
- Storage Cost (high)
- Computing Cost (low)
- Access Latency (low)
There is a challenge to be solved in this implementation, there is a time gap between ETL and the application , if this time gap is not dealt with then the user will feel the data loss. A common practice is to reserve a buffer, for example, for an application program to use T for hot/cold junction, so T-1, T-2 will be the cold data accordingly, and vice versa.
In order to avoid the time gap, ETL will prepare the data of T at T-1 in advance at the launch time. Nevertheless, if the data for the T time period is updated then it is possible to encounter data inconsistencies, which require additional handling.
- Implementation Complexity (medium)
Cold data archiving
The solutions mentioned above are all big technical compromises to minimize business impact, and there is no way to significantly reduce the cost of implementing data tiering in this way.
If we are willing to sacrifice most of the user stories, can we optimize the cost greatly? Yes, absolutely.

The architecture is also two storage, but one is a database and the other is an object storage system. When we decide the conditions of the cold data, we can start the archiving.
Because of the characteristics of object storage, no schema, no index and long access latency, cold data is not a useful option for applications. For applications, cold data is like disappearing suddenly, and the same is true for users.
This is how the bank transaction records were handled in the first place. Both the application and the user no longer have access to cold data, which is irrelevant in most usage scenarios. Once we need cold data, for example if I want to see a disputed account from a year ago, I have to go to the bank and request a data access.
The data still exists, it’s just no longer easily accessible.
- Readable (v)
- Writable (x)
- Aggregatable (x)
Some applications may keep a history export feature, but more often it’s like a bank where the data is removed right from the user interface.
But this way we get a dramatic cost optimization, because object storage is much less pricey than databases.
- Storage Cost (low)
- Computing Cost (x)
- Access Latency (high)
We’ve sacrificed the business requirements, and instead, we’ve dramatically reduced costs. We can see that I’ve put a cross in the computing cost column because we no longer need to do computing on cold data. Of course, this way we also get an optimized development cost.
- Implementation Complexity (low)
If such a trade-off is adopted, do not think about satisfying business requirements, as it will only be counterproductive.
Data warehousing
The solutions mentioned so far are all extreme, either highly satisfying business requirements or highly dependent on cost optimization. Is there a middle-of-the-spectrum approach?
Actually, data warehousing is a solution that can satisfy part of the business requirements and achieve part of the cost optimization.
Data warehousing is the process of putting cold data into a “place” that offers low storage costs and the ability to scale computing resources to provide performance when necessary.
Data warehousing services are available in various public clouds, such as AWS Redshift and GCP BigQuery; in addition, there are many vendors offering similar solutions, such as Snowflake.
These data warehousing services have the following characteristics.
- Nearly unlimited and low-cost storage.
- Scale to zero when not in use to save costs.
- Ability to compute large amounts of data.
- Response times are not short, at least much longer than databases.

This architecture is pretty similar to simple data archiving, but the difference is that data warehousing provides the ability to perform complex operations, so it can meet some of the business requirements. Of course, everything has a price, these computing power is the cost of exchange.
- Readable (v)
- Writable (x)
- Aggregatable (v)
The reason why there is only a partial business requirement is limited by the latency of data warehouse responses, which may not be experienced well if it is a user-facing feature, so the user scenario needs to be designed in such a way for users to expect a long wait.
In addition, although the data warehouse provides the ability to write, it is not suitable for the regular writing of applications. Because of the long latency and the high cost of a single write, batch processing with archiving is often used.
- Storage Cost (medium)
- Computing Cost (high)
- Access Latency (medium)
It is worth mentioning if the original main database is SQL based, then this transformation is not a major impact on the application, because the data warehouse has SQL support. If the data warehouse and archive are already in place, then the effort of transformation is even less.
However, the latency faced in obtaining data requires a reasonable process, and if the data warehouse is operated as if it were a database, then problems such as timeout may be encountered frequently. This can be mitigated by redesigning the business process.
- Implementation Complexity (medium)
Conclusion
In the previous section we analyzed the properties and trade-offs of different data tiering approaches, so that we can summarize them in a table and assign a rank to them.

[1]: Data warehousing is also through object storage, but because it creates a catalog and supports selectable fields, it is generally more efficient than just object storage.
[2]: This refers to the fact that the main database is SQL based, which makes it less difficult to implement because of the compromises in the user scenarios. But if the main database is not SQL based, it’s a totally different story.
In fact, there are many variations of these four solutions, depending on the business and technical trade-offs will be adjusted in some details, but the overall concept is basically the same.
We can realize that the task of data tiering, which feels very technical-driven, is essentially business-driven. From the beginning of the user behavior research to the subsequent adjustment of business requirements, this series of trade-offs will affect the entire system experience.
Even so, these trade-offs still require a lot of technical selection behind the scenes, in other words, it is not only a business-driven task.
We all know that data tiering is important and necessary, but how to get the whole thing launch depends on a lot of communication and mutual trust between the business side and the technical side.
With the table above, I believe I can provide you with an easy-to-understand overview of how to adjust your business requirements on a case-by-case basis.
Stackademic 🎓
Thank you for reading until the end. Before you go:
Originally published on Medium