What Is Tiered Storage? Hot & Cold Storage for Databases

Learn what tiered storage is, why databases need hot and cold storage, and how it can keep historical data accessible without maintaining a second reporting system.

After working for years with manufacturing and enterprise companies, I kept seeing the same database problem.

A company starts with a database that is perfectly manageable.

Then the years pass.

Orders accumulate. Production records accumulate. Machine events accumulate. Inventory history accumulates. Audit records accumulate.

Eventually, the company has 10, 15, or even 20 years of historical data.

Most of that data is rarely used.

But rarely used does not mean useless.

Someone might suddenly need an invoice from seven years ago.

A production manager might want to compare today's manufacturing output with a period from five years ago.

Finance might need an old order.

An auditor might request records that nobody has touched in years.

So the data cannot simply be deleted.

And this is where tiered storage becomes very interesting.

What is tiered storage?

Tiered storage means storing data differently depending on how frequently it is accessed and how quickly it needs to be available.

The simplest model:

Database data splits into hot storage on SSD or NVMe and cold storage on object stores such as S3, Blob, or GCS

Recent data stays in hot storage, where the database can access it very quickly.

Older data can move into a cold storage tier, where storing large amounts of information is significantly more economical.

The important idea is:

Old data remains available, but we stop treating every historical row as if it needs the same performance as today's active data.

An easy example

Imagine a company has accumulated 5 TB of database data.

But when you look at what the application actually uses every day, you discover that only about 300 GB is regularly accessed.

A 5 TB database with about 300 GB of hot data and 4.7 TB of historical data

The traditional approach is basically: keep 5 TB inside expensive database storage.

Tiered storage asks a different question:

Does all 5 TB actually need database-level performance?

Perhaps what the application really needs is 300 GB of fast PostgreSQL storage for frequently accessed data, plus 4.7 TB of cheaper historical storage for data that is only occasionally accessed — while still keeping all 5 TB logically available.

That is the basic idea.

Why do we need tiered storage more than ever?

The problem isn't new.

What has changed is how quickly databases are accumulating data.

Modern applications keep much more history than applications did years ago.

We now commonly store things such as:

  • application events
  • audit trails
  • customer activity
  • notifications
  • machine and IoT events
  • production records
  • chat messages
  • API request history
  • JSON payloads
  • AI conversations
  • AI tool calls
  • agent execution traces

Many of these records are generated automatically.

Humans don't even have to create the data anymore.

Software creates data continuously.

Manufacturing is a perfect example

This is something I've seen repeatedly while working with manufacturing companies.

A production system may contain years of:

  • production orders
  • machine activity
  • quality records
  • material movements
  • inventory changes
  • purchasing history
  • sales orders
  • maintenance events
  • audit history

The business often has a very long memory.

A company may have data going back many years.

But access is heavily skewed toward recent information.

Think of it like this: today's order might be touched constantly. An invoice from ten years ago might be accessed once a year.

Should that older record really occupy the same expensive database tier as an order created five seconds ago?

That is the problem tiered storage is trying to solve.

Why not simply delete old data?

Because businesses often can't.

Historical data has value.

It may be needed for:

  • regulations
  • auditing
  • customer support
  • financial investigations
  • production comparisons
  • warranty cases
  • historical reporting
  • trend analysis
  • machine troubleshooting
  • legal requirements

Sometimes nobody knows which historical row will become important.

A machine fails today and suddenly an engineer wants to compare its behavior with a similar failure from six years ago.

The historical data went from:

"We never use this."

to:

"We need this immediately."

That happens more often than people think.

So why not move old rows into another cheaper database?

Because you now have two databases.

An application splitting between a production database for recent data and an archive database for historical data

Now every feature that needs historical information has to understand both systems.

That sounds small at first.

It usually isn't.

Reporting becomes more complicated

Imagine an ERP originally had this report:

sql snippetSQL
SELECT customer_id,       SUM(total)FROM ordersWHERE order_date BETWEEN $1 AND $2GROUP BY customer_id;

Easy.

Everything is in orders.

Now you archive orders older than three years.

Suddenly that same report might need:

One five-year report splitting into a Postgres query, an archive query, and a merge

What used to be one query becomes two queries, two systems, merge logic, error handling, and consistency logic.

And this happens for every feature that needs both recent and historical data.

You may end up rebuilding your reports

This is one of the biggest hidden costs of moving historical data into another system.

Imagine the original application already contains:

  • ERP reports
  • dashboards
  • customer screens
  • exports
  • business logic
  • joins
  • permissions
  • filters

All of these understand the original database.

If historical data moves somewhere else, you may need to recreate some of that logic.

You saved money on storage.

But you introduced more engineering.

And joins become particularly painful

Imagine you have customers, orders, order_items, and products.

Originally:

sql snippetSQL
SELECT ...FROM customers cJOIN orders o    ON o.customer_id = c.idJOIN order_items i    ON i.order_id = o.idJOIN products p    ON p.id = i.product_id;

PostgreSQL knows how to do the join.

But imagine old orders and order_items have been moved somewhere else.

Now the application has to understand that some rows live here, in PostgreSQL, and some live there, in a historical database.

The simple relational model starts leaking into the application architecture.

That is something I think database tiered storage should try to avoid.

Archiving often creates another data pipeline

Over time, what began as "let's move old rows somewhere cheaper" can evolve into:

  1. PostgreSQL
  2. CDC / ETL
  3. Kafka
  4. a data lake
  5. a warehouse
  6. historical reports

There is nothing inherently wrong with this architecture.

For large analytics workloads it may be exactly what you want.

But if your only problem was "most of my PostgreSQL table is old and rarely accessed," this can be a lot of infrastructure to introduce just to solve storage lifecycle.

This is where database tiered storage is different

A good database tiering architecture tries to preserve the logical database while changing the physical storage.

Instead of the application talking to a production database and a historical database, you want something closer to this:

An application sending one SQL query to a database that reads hot and cold storage and returns one result

The storage system knows there are two tiers.

Ideally, the application doesn't have to.

The application should still ask the same question

For example:

sql snippetSQL
SELECT *FROM ordersWHERE customer_id = 100ORDER BY created_at DESC;

The storage layer can determine whether the query needs recent data, historical data, or both, then combine the results.

From the application's perspective:

Same table.

Same query.

Same report.

That is the interesting promise of database-native tiered storage.

Cold storage should not make hot queries slower

This is equally important.

Suppose your data looks like a long historical range from 2020 through 2026, with only the recent slice still hot, and the application asks:

sql snippetSQL
SELECT *FROM ordersWHERE created_at >= now() - interval '7 days';

A good tiered-storage system should know:

Historical data ends before this query begins.

So the query reads hot storage and returns a result. Cold storage stays untouched.

The existence of cold data should not automatically mean every query needs to access it.

How can the database know which cold data it needs?

Cold storage can maintain small pieces of metadata describing what each stored segment contains.

For example:

Segment

Range

Matches created_at = '2022-05-17'

Segment A

2022-01 to 2022-03

No

Segment B

2022-04 to 2022-06

Yes

Segment C

2022-07 to 2022-09

No

It doesn't have to read everything.

And columnar formats such as Parquet can divide the file further into row groups with their own statistics.

Conceptually:

Query pruning from 5 TB of historical storage down to the selected columns actually read

Cold storage can therefore be slower than hot storage without necessarily meaning every historical query requires scanning the entire archive.

Tiered storage is not the same as backup

These concepts are easy to mix together.

Technology

Purpose

Hot database

Serve frequently accessed application data

Tiered / cold storage

Keep less frequently used data on cheaper storage while it remains accessible

Archive

Preserve old data, often outside normal application queries

Backup

Recover after data loss or corruption

Data warehouse

Run analytical workloads over large datasets

Tiered storage does not replace backups.

And it doesn't necessarily replace a warehouse either.

If you need large-scale analytics, a warehouse or analytical engine can still make sense.

The purpose is different.

Which database tables benefit the most?

Tiered storage works particularly well when data becomes less useful to the active application as it ages.

For example:

Workload

Tiered-storage fit

Manufacturing history

Excellent

Audit records

Excellent

Chat messages

Excellent

AI conversations and traces

Excellent

Notifications

Strong

Historical orders

Strong

IoT and machine events

Strong

Activity feeds

Strong

Account balances

Weak

Frequently changing inventory

Weak

The key pattern is:

Data lifecycle from created, to frequently accessed, to less frequently accessed, to historical but still occasionally needed

That last line is important.

If old data can simply be deleted, you don't really have a tiered-storage problem.

AI is making this problem even bigger

Manufacturing companies already taught me how valuable historical data can become after many years.

AI applications are now creating another version of the same problem — only much faster.

Multiply this by thousands or millions of users and the amount of historical application data can grow extremely quickly.

Yet an AI execution from three years ago probably doesn't require the same latency as an interaction happening right now.

It may still need to exist.

It simply doesn't necessarily need to stay hot.

Think of it like your office

Imagine keeping every document your company has ever created directly on your desk.

Today's paperwork belongs there. So does the current customer contract, and the laptop.

Invoices from 2015, production records from 2012, old audit documents, and every completed order ever do not.

Eventually you would need a very large desk.

In real life, we naturally create tiers:

Office analogy with a desk for things needed constantly, a cabinet for occasional documents, and an archive room for records that cannot be thrown away

The important thing is that you still know where everything is.

Tiered storage applies the same idea to a database.

The real goal: separate data retention from data performance

I think this is the easiest way to understand tiered storage.

A company may want to retain 10 years of data without needing 10 years of data times highest-performance storage.

Those are two different requirements.

Ten years of retained data split into 5 to 10 percent that needs fast access and 90 to 95 percent that only needs to exist

Once those requirements are separated, database architecture can become much more efficient.

PostgreSQL and tiered storage

This idea becomes particularly interesting with PostgreSQL.

Instead of replacing PostgreSQL with another database just because the historical tables became large, another approach is:

Keep PostgreSQL as the application interface and extend where its data can live.

That means developers can potentially continue using familiar:

  • SQL
  • PostgreSQL drivers
  • ORMs
  • permissions
  • joins
  • existing reports
  • existing applications

while the storage architecture underneath becomes more efficient.

This is also one of the ideas behind KoldStore.

KoldStore is exploring tiered storage for PostgreSQL where active rows remain in PostgreSQL while historical rows can be stored as compressed Parquet on cheaper storage.

Conceptually:

A PostgreSQL table with hot rows in the heap and indexes, and cold rows as Parquet segments on object storage

The goal is not to create a second application database.

It is to let the storage layer manage the lifecycle while PostgreSQL remains the interface developers already know.

The future database may be a logical database, not one physical storage system

Historically, we often thought:

Database = one database server + one storage system.

But perhaps a modern database looks more like:

One SQL interface over a logical table spanning hot NVMe, warm SSD or HDD, and cold object storage with Parquet

The application doesn't necessarily care which tier contains a row.

It asks for data.

The database figures out where that data lives.

Final thought

Tiered storage starts with a very simple observation:

Data doesn't have the same value to performance throughout its entire life.

Today's production record may need to be available in milliseconds.

The same record ten years later may only be needed once during an audit.

Both records are important.

But that doesn't mean both need the same storage.

For companies with years of manufacturing, ERP, CRM, messaging, event, audit, or AI history, the question is becoming less:

"How do we keep making our database bigger?"

and more:

"How do we keep all of our history without keeping all of our history hot?"

That is the problem tiered database storage is trying to solve.

And the best version of it should have a very simple outcome:

Your data gets cheaper as it gets older.

Your application keeps querying it the same way.