Tiered storage for cold data lets you move infrequently accessed database objects — tables, indexes, materialized views, and LOB fields — from local disk to OSS (Object Storage Service), reducing storage costs without requiring any changes to how your application queries data.
The typical workflow is:
Check compatibility — Confirm your cluster version and region support the feature.
Enable tiered storage — Turn on the feature from the PolarDB console (one-time, irreversible; triggers a cluster restart).
Move data to cold storage — Use SQL statements to transfer objects to the OSS tablespace.
Configure the materialized cache — Tune
polar_smgrcache_sizeto cache frequently accessed cold data locally and reduce OSS read latency.Query and manage cold data — Run standard DML/DQL statements; no application changes required.
Applicability
Version requirements
| PolarDB for PostgreSQL version | Minimum minor engine version |
|---|---|
| PostgreSQL 16 | 2.0.16.9.6.0 |
| PostgreSQL 14 | 2.0.14.10.21.0 |
Individual cold storage for LOB fields is not supported on PostgreSQL 16.
Supported regions
| Area | Region |
|---|---|
| China | China (Hangzhou) |
| China | China (Shanghai) |
| China | China (Shenzhen) |
| China | China (Beijing) |
| Other | Singapore |
Limitations
Enabling the feature is irreversible. Once enabled, tiered storage cannot be disabled. To remove cold data, delete the objects stored in OSS. If no cold data is stored, you are not charged for the feature.
Clusters with hot standby have restrictions. You cannot enable tiered storage on a PolarDB for PostgreSQL cluster that has hot standby enabled. To enable the feature in this scenario, contact us for assistance.
Changing the primary zone requires assistance. After tiered storage is enabled on a cluster with hot standby, you cannot change the primary zone directly. Contact us for assistance.
Some DDL statements are unsupported:
CREATE DATABASE dbname TABLESPACE OSS;— Creating a database directly in the OSS tablespace is not supported.ALTER DATABASE dbname SET TABLESPACE OSS;— Transferring an entire database to the OSS tablespace with a single command is not supported.
Enable tiered storage
Enabling tiered storage restarts the PolarDB cluster. Schedule this operation during a maintenance window.
Log on to the PolarDB console. In the left navigation pane, click Clusters. Select the region where your cluster is located, find the cluster, and click its ID.
In the left navigation pane, choose Settings And Management > Cold Data Tiered Storage.
On the PolarDB cold data tiered storage page, click Enable.

After enabling, the Archive List page appears. It contains an Overview section and a Data Archive List section. The Data Archive List section has three tabs: Whole table Archive list, Partition Table Archive List, and LOB Field Archive List.
If no cold data has been transferred yet, the Data Archive List is empty. Data remains on high-speed disk storage by default until you explicitly move it to the OSS tablespace.
Move data to cold storage
After enabling the feature, move data to the OSS tablespace using SQL statements. All subsequent DML and DQL operations on objects in the OSS tablespace are transparent — no application changes are required.
Standard tables, indexes, and materialized views
Move existing objects to cold storage:
ALTER TABLE tblname SET TABLESPACE OSS;
ALTER INDEX idxname SET TABLESPACE OSS;
ALTER MATERIALIZED VIEW mvname SET TABLESPACE OSS;ALTER TABLE tblname SET TABLESPACE OSStransfers only the table data. To also move the table's indexes, runALTER INDEXseparately for each index.
Create new objects directly in cold storage:
Method 1: Specify TABLESPACE OSS in the CREATE statement.
CREATE TABLE tblname (...) TABLESPACE OSS;
CREATE TABLE tblname (...) TABLESPACE OSS AS SELECT ...;
CREATE INDEX idxname ON tblname (columnname) TABLESPACE OSS;
CREATE INDEX idxname ON tblname USING GiST (columnname) TABLESPACE OSS;
CREATE MATERIALIZED VIEW table_name TABLESPACE OSS AS query [ WITH [ NO ] DATA ];Method 2: Set the session's default tablespace to oss before creating objects.
SET default_tablespace = 'oss';
CREATE TABLE tblname (...);
CREATE INDEX idxname ON tblname (columnname);
CREATE MATERIALIZED VIEW table_name AS query [ WITH [ NO ] DATA ];After setting default_tablespace = 'oss', all CREATE TABLE, CREATE INDEX, and CREATE MATERIALIZED VIEW statements in the session create objects directly in the OSS tablespace. To stop creating objects in cold storage, reset the default:
RESET default_tablespace;LOB fields
Individual cold storage for LOB fields is not supported on PostgreSQL 16.
LOB fields — including blob, text, json, jsonb, array, and spatio-temporal data types — are often large and infrequently updated. You can move only the LOB fields to cold storage while keeping all other columns on local disk.
-- Create a table with a LOB field.
CREATE TABLE test_large_object (id serial, val text);
-- Move the LOB field to cold storage.
ALTER TABLE test_large_object ALTER COLUMN val SET (storage_type = 'oss');
-- New data written to this field is now stored in OSS.
INSERT INTO test_large_object (val)
VALUES ((SELECT string_agg(random()::text, ':') FROM generate_series(1, 10000)));Set storage_type = 'oss' on the column before writing data. Only data written after this change is stored in OSS; existing data is not migrated retroactively.
Partitioned tables
Partitioned tables are a common use case for cold storage. You can move all partitions or only specific expired partitions to the OSS tablespace.
Move all partitions to cold storage:
Method 1: Run ALTER TABLE ... SET TABLESPACE OSS on each child partition.
-- prt1 is the parent partitioned table.
-- prt1_p1 and prt1_p2 are child partitions.
ALTER TABLE prt1_p1 SET TABLESPACE OSS;
ALTER TABLE prt1_p2 SET TABLESPACE OSS;Method 2: Create the parent table in the OSS tablespace. Child partitions inherit the tablespace.
CREATE TABLE prt1 (a int, b int) PARTITION BY RANGE (a) TABLESPACE OSS;
-- Child partitions inherit the OSS tablespace from the parent.
CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250);
CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500);Method 3: Set default_tablespace = 'oss' before creating the partitioned table.
SET default_tablespace = 'oss';
CREATE TABLE prt1 (a int, b int) PARTITION BY RANGE (a);
CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250);
CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500);Move only expired partitions to cold storage:
To reduce costs without affecting query performance on active partitions, move only expired (infrequently accessed) child partitions to the OSS tablespace. Active partitions remain on local disk.
-- prt1_p1 is an active child partition — leave it on disk.
-- prt1_p2 is an expired child partition — move it to OSS.
ALTER TABLE prt1_p2 SET TABLESPACE OSS;Configure the materialized cache
The materialized cache stores frequently accessed cold data blocks on local disk, reducing OSS read latency. When tiered storage is enabled, a small default cache is created automatically to store metadata and handle I/O merging.
Tune the cache size using the polar_smgrcache_size parameter:
| Value | Cache size |
|---|---|
0 | Disabled |
1 | 1 GB |
2 | 2 GB |
128 | 128 GB (maximum) |
To modify the parameter:
In the PolarDB console, go to the cluster details page.
In the left navigation pane, choose Settings And Management > Parameters.
Find
polar_smgrcache_sizeand click Modify.Set the value, then click Submit Changes in the upper-left corner. In the Save Changes dialog, click OK.
The cluster restarts and the new cache size takes effect.
If you set polar_smgrcache_size to 0 after cold data is in active use, the cache is disabled. This can cause crash recovery to become very slow, and the parameter cannot be re-enabled during the restart. To recover, contact us to request that the cache be re-enabled.
Monitor cache usage:
-- Install the monitoring extension.
CREATE EXTENSION polar_monitor;
-- Query current cache usage.
SELECT * FROM polar_smgrcaches;The polar_smgrcaches view returns the following fields:
| Field | Description |
|---|---|
smgrcache | Cache ID |
relfilenode | Table file associated with this cache entry |
relchunknumber | Position of the cache entry in the table file |
nblocks | Size of the cache entry (in blocks) |
dirty | Whether the cache entry contains dirty blocks |
usagecount | Usage count |
pinning_backends | Reference count |
To manage the cache manually:
-- Flush all cache entries to OSS.
SELECT polar_flush_smgrcache();
-- Evict all cache entries from local disk.
SELECT polar_evict_smgrcache();Query and manage cold data
Query cold data
DML and DQL statements on objects in the OSS tablespace are fully transparent — no SQL changes or application modifications are required. Standard SELECT, INSERT, UPDATE, and DELETE statements work the same way as on local tables.
Restore cold data to local disk
Data is compressed when transferred to OSS. If you need to move data back to a local disk tablespace, make sure the target disk has enough free space. The space required is typically 1.4 to 4 times the storage space that the data occupies on OSS.
Delete cold data
SQL statements for deleting cold tables, indexes, or materialized views work the same as for local objects:
DELETE FROM tblname WHERE ...;
TRUNCATE TABLE tblname;
DROP TABLE tblname;