
By Tiger Data Team
Updated at May 26, 2026
AWS Timestream LiveAnalytics closed to new customers in June 2025. Engineers who built time-series workloads on LiveAnalytics are now in active migration research. This guide is for that audience: engineers who have decided to move off Timestream and want a concrete technical path to PostgreSQL on Tiger Cloud.
Full disclosure: Tiger Data publishes this guide and sells Tiger Cloud. We think PostgreSQL is the right destination for most Timestream migrations. Where the InfluxDB path fits your workload better, we'll tell you.
This guide covers schema translation, data export and ingest, query rewrites from Timestream Query Language (TQL) to TimescaleDB SQL, Grafana dashboard migration, a cardinality audit, Tiger Cloud setup, and a pre/during/post cutover checklist. It does not cover migrating to AWS Timestream for InfluxDB. For a broader alternatives comparison, see AWS Timestream Alternatives: Your Migration Options After LiveAnalytics.
AWS's default recommendation for LiveAnalytics departures is Timestream for InfluxDB. Engineers reading migration documentation will have seen this. It is worth addressing directly before walking through technical steps.
The choice comes down to three questions.
Cardinality. AWS's own guidance suggests the InfluxDB path is best suited to workloads with fewer than approximately 10 million unique series keys. Engineers running high-cardinality industrial IoT workloads, where the number of unique device/sensor/region combinations grows into the tens or hundreds of millions, may hit that ceiling on the InfluxDB path. Tiger Cloud on PostgreSQL has no built-in series cardinality limit. Cardinality is a schema design and indexing concern, not a hard system ceiling.
SQL compatibility. Timestream for InfluxDB uses InfluxQL and Flux. If your engineering team's tooling, ORM layers, BI tools, or data pipelines expect PostgreSQL-compatible SQL, the InfluxDB path adds a query language migration on top of the database migration. That is a real cost.
Ecosystem breadth. PostgreSQL brings JOIN support, foreign keys, PostGIS for geospatial data, pgvector for ML embeddings, pg_cron for scheduled jobs, row-level security, and the full pg_* extension ecosystem. Timestream for InfluxDB provides none of these.
Use this table to decide:
Choose Timestream for InfluxDB if... | Choose Tiger Cloud (PostgreSQL) if... |
You already use InfluxQL or Flux | Your team knows SQL and wants PostgreSQL compatibility |
Your cardinality is under ~10M series | Your workload exceeds ~10M unique series |
You want to stay in the AWS managed service ecosystem | You need JOIN support, PostGIS, pgvector, or other PostgreSQL extensions |
You don't need relational joins or PostgreSQL extensions | You use Grafana with a PostgreSQL data source |
| You want a cloud-portable database not locked to AWS infrastructure |
Use this table to find the right path before investing in migration steps that don't fit your workload.
Before you can map Timestream schema to PostgreSQL, you need to understand what Timestream's model actually is. Three concepts matter:
Tables. Timestream tables are not equivalent to PostgreSQL tables. Each table has a fixed structure: a time column (always a timestamp), dimension columns (string key-value metadata), and measure columns (the actual metric values).
Dimensions. High-cardinality string attributes that identify the source of a measurement, such as device_id, region, and sensor_type. Timestream indexes dimensions for fast filtering but stores them as strings only.
Measures. The time-varying values you are actually recording. A Timestream record can contain multiple measure columns (multi-measure records) or a single measure per row (single-measure records, the older format). You may have either format depending on when the table was created.
Before starting migration, run DESCRIBE TABLE in TQL to retrieve the effective schema for each table you are migrating. Timestream lacks traditional DDL, so your schema may not be documented elsewhere.
A sample Timestream table for device telemetry looks like this:
Table: device_metrics
time (TIMESTAMP)
device_id (DIMENSION, VARCHAR)
region (DIMENSION, VARCHAR)
sensor_type (DIMENSION, VARCHAR)
temperature (MEASURE, DOUBLE)
pressure (MEASURE, DOUBLE)
battery_pct (MEASURE, BIGINT)The mapping to PostgreSQL columns is not a one-to-one translation, which is where most migration plans go wrong on the first attempt.
Getting the schema translation right before you write any migration code saves significant rework. This is where to start.
The core mapping rule: Timestream dimensions become PostgreSQL columns (text or varchar). Timestream measures become PostgreSQL columns with matching data types. The Timestream time column becomes the TimescaleDB hypertable partition key (timestamptz).
Data type mapping:
Timestream type | PostgreSQL type | Notes |
TIMESTAMP | TIMESTAMPTZ | Always use timezone-aware timestamps for time-series data |
VARCHAR (dimension) | TEXT | Dimensions are always string; map directly |
DOUBLE | DOUBLE PRECISION | Standard float8 |
BIGINT | BIGINT | Direct mapping |
BOOLEAN | BOOLEAN | Direct mapping |
Multi-measure record | Multiple columns | Each measure becomes its own column |
PostgreSQL DDL example. Here is the hypertable equivalent of the Timestream table shown above:
CREATE TABLE device_metrics (
time TIMESTAMPTZ NOT NULL,
device_id TEXT NOT NULL,
region TEXT,
sensor_type TEXT,
temperature DOUBLE PRECISION,
pressure DOUBLE PRECISION,
battery_pct BIGINT
);
SELECT create_hypertable('device_metrics', by_range('time'));The create_hypertable() call converts the standard PostgreSQL table into a TimescaleDB hypertable, enabling automatic time-based partitioning. From that point on, it behaves like a normal PostgreSQL table for reads and writes.
Multi-measure vs single-measure records. Multi-measure records (where each row contains all measure values) translate cleanly to the schema above. Single-measure records (the older format, where each row contains a single measure_name value and a single measure_value) require a pivot during migration. Multiple Timestream rows with different measure_name values for the same timestamp and device must be combined into a single PostgreSQL row. The most practical approach is GROUP BY + conditional aggregation during the S3 export processing step, or batching at the application level during ingest.
Cardinality design note. In Timestream, dimension cardinality is managed by the service. In PostgreSQL, workloads with very high-cardinality dimension values (tens of millions of unique device_id strings) benefit from a lookup table pattern: store device_id as an integer foreign key referencing a separate devices table rather than repeating long string values in every row. This is an optional optimization for the largest-scale workloads, not a requirement for getting started.
Timestream supports two export mechanisms:
AWS Data Export (recommended for large datasets): exports to S3 as Parquet or CSV via a managed export job. Parquet is the better choice for large historical exports because of its columnar compression.
Scheduled queries with UNLOAD: TQL-based export to S3, useful for filtered or transformed exports but less convenient for full-table bulk export.
For most migrations, use the AWS Data Export feature. The output lands in S3 as columnar Parquet files with the original column structure intact. Before writing your ingest step, verify how the time column is formatted in the export output (epoch milliseconds or ISO 8601), because this affects how you parse it during ingest.
Chunk your exports by time. For large historical datasets, export in time-bounded chunks (by month or quarter) rather than a single full-table export. Timestream's query-side has memory and timeout constraints that can cause full-table exports to fail or produce incomplete results on large tables.
Dual-write during cutover. Timestream does not support continuous replication to an external destination. During the migration period, you will need dual-write: application writes go to both Timestream and Tiger Cloud simultaneously until you validate the cutover. The cutover checklist at the end of this guide covers the dual-write pattern in detail.
Once your Timestream export lands in S3, you have three ingestion paths:
COPY from S3 (recommended for historical data). The PostgreSQL COPY command reads CSV files directly. For Parquet files, convert to CSV first using a lightweight tool (DuckDB is effective for this), then COPY:
COPY device_metrics (time, device_id, region, sensor_type, temperature, pressure, battery_pct)
FROM '/path/to/exported_chunk.csv'
WITH (FORMAT CSV, HEADER true);For large datasets, parallelize the COPY across time-bounded chunks. TimescaleDB hypertables accept parallel COPY operations without coordination issues because each chunk lands in a separate partition.
Standard PostgreSQL INSERT for ongoing writes (dual-write period). TimescaleDB hypertables accept standard PostgreSQL INSERT statements. No special syntax is required. This is an important point for engineers unfamiliar with TimescaleDB: it is PostgreSQL. Any PostgreSQL-compatible driver, including psycopg2, asyncpg, pgx, JDBC, and pg for Node.js, connects and writes using the same syntax your application already uses.
INSERT INTO device_metrics (time, device_id, region, sensor_type, temperature, pressure, battery_pct)
VALUES (NOW(), 'dev-001', 'us-east-1', 'thermostat', 22.4, 101.3, 87);Tiger Cloud connection string. Use the standard PostgreSQL URI format:
postgresql://username:password@<service-host>:5432/database_name
Find your specific service host in the Tiger Cloud console under connection settings. Tiger Cloud exposes a standard PostgreSQL wire protocol endpoint, so any PostgreSQL-compatible driver connects without modification.
Enable Hypercore compression after ingest. Once your historical data is loaded and validated, enable Hypercore compression on the hypertable. This is a one-command operation:
ALTER TABLE device_metrics SET (
timescaledb.compress,
timescaledb.compress_segmentby = 'device_id'
);
SELECT add_compression_policy('device_metrics', INTERVAL '7 days');For time-series workloads, Hypercore compression typically reduces storage by 90% or more for historical data. Timestream's pricing model accumulates storage costs without equivalent compression transparency, which is a difference that compounds over time on large historical datasets.
TQL and PostgreSQL SQL handle the same operations differently. Here are the most common patterns side by side:
Query pattern | Timestream TQL | TimescaleDB SQL |
Recent records |
|
|
Time-bucket aggregation (1-minute bins) |
|
|
Filter by dimension (single-measure schema) |
|
|
Latest value per device | Subquery with |
|
Gap fill | No native gap fill in TQL |
|
Multi-day downsampling |
|
|
Single-measure record note. If your Timestream schema used single-measure records, the WHERE measure_name = 'temperature' filter in TQL has no direct equivalent in PostgreSQL. That transformation happens at the schema level during migration: each distinct measure_name value becomes its own column. Once the schema is correct, you reference the column directly.
Continuous aggregates. Timestream's scheduled queries for pre-computed aggregations have a functional equivalent in TimescaleDB: continuous aggregates. They refresh incrementally in the background, updating only what changed since the last refresh, and are queryable like a standard view. Engineers who relied on Timestream scheduled queries for dashboard performance should look at continuous aggregates as their replacement. See How to Get Faster Aggregated Data in PostgreSQL for the implementation pattern.
Engineers running Timestream almost always use Grafana via the official Grafana Amazon Timestream data source plugin. Switching databases requires switching data sources and rewriting panel queries. This is panel-by-panel work. There is no bulk replace tool in Grafana.
Step 1: Add the PostgreSQL data source. In Grafana, go to Settings > Data Sources > Add data source > PostgreSQL. Enter the Tiger Cloud connection string. Test the connection before touching any dashboards.
Step 2: Inventory affected dashboards. Identify which dashboards use the Timestream data source. Grafana's data source usage report helps here, but manual review is often faster for smaller installations.
Step 3: Rewrite panel queries. For each panel, rewrite the TQL query to PostgreSQL SQL. Use the query rewrite table above as reference. The key difference in Grafana's PostgreSQL data source: use $__timeFilter(time) as the time range macro rather than Timestream's equivalent. Example:
-- Timestream panel query
SELECT bin(time, $__interval), avg(temperature)
FROM "mydb"."device_metrics"
WHERE $__timeFilter(time) AND "device_id" = '$device'
GROUP BY 1
-- PostgreSQL panel query
SELECT $__timeGroupAlias(time, $__interval), avg(temperature)
FROM device_metrics
WHERE $__timeFilter(time) AND device_id = '$device'
GROUP BY 1Step 4: Update variable queries. Dashboard variable queries (the dropdowns that filter by device or region) must also be rewritten. A TQL variable query for a device list becomes:
SELECT DISTINCT device_id FROM device_metrics ORDER BY 1
Format compatibility. Grafana's time-series panel expects a time column and value columns. TimescaleDB's query output matches this expectation natively. Your visualization types (time series, stat, table) do not need to change.
Timestream manages cardinality at the service level. Engineers rarely had to think about it. PostgreSQL manages cardinality at the table and index level, so schema design choices matter here.
Before committing to a migration path, measure your current series count. Run this in TQL over a 24-hour window (full-table cardinality queries on large tables are expensive and may time out):
SELECT COUNT(DISTINCT device_id, region, sensor_type) AS approx_series_count
FROM "mydb"."device_metrics"
WHERE time BETWEEN ago(24h) AND now()Interpreting the result:
Under ~1 million unique series: Standard PostgreSQL column design. No special considerations.
1 million to 10 million series: Consider storing device_id as an integer foreign key referencing a devices lookup table rather than repeating full strings in every row.
Over 10 million series: Tiger Cloud handles this natively through hypertable partitioning and index design. The InfluxDB path is not recommended at this scale per AWS's own service limit documentation.
Tiger Cloud on PostgreSQL has no built-in series cardinality limit. For high-cardinality industrial IoT workloads, this is the meaningful difference between the two migration paths.
This is a pre-migration setup reference, not a substitute for Tiger Cloud documentation. Where the docs have the precise details, we point you there.
Step 1: Create a Tiger Cloud service. Select a region close to your application layer. For IoT and telemetry workloads, region proximity matters for write latency.
Step 2: Create your database and user.
CREATE DATABASE telemetry_db;
CREATE USER app_user WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE telemetry_db TO app_user;Step 3: Enable the TimescaleDB extension.
CREATE EXTENSION IF NOT EXISTS timescaledb;
Step 4: Create the hypertable. Use the DDL from the schema mapping section. One week is a reasonable starting chunk interval for high-ingest IoT workloads:
SELECT create_hypertable('device_metrics', by_range('time', INTERVAL '1 week'));
Step 5: Enable Hypercore compression. Apply compression after validating ingest. Use the command from the ingestion section.
Step 6: Set up a data retention policy (equivalent to Timestream's magnetic store retention):
SELECT add_retention_policy('device_metrics', INTERVAL '90 days');
Use this as a team coordination document during the migration. Share it with whoever owns the application-layer changes and whoever owns the Grafana dashboards before you start.
Run the cardinality audit on all Timestream tables being migrated
Document all Timestream tables: dimension columns, measure columns, data types, record format (single-measure or multi-measure)
Identify all application code writing to Timestream (search for WriteRecords API calls and Timestream SDK imports)
Identify all application code reading from Timestream (TQL queries, Grafana panels, scheduled queries, reports)
Identify all downstream consumers (Grafana dashboards, data pipelines, scheduled aggregation jobs)
Set up Tiger Cloud service and validate connection from your application environment
Create hypertable schema and run a test ingest with a small data sample (one day of data)
Run a sample TQL query and its PostgreSQL equivalent on test data; verify consistent results
Enable dual-write: application writes to both Timestream and Tiger Cloud simultaneously
Export Timestream historical data to S3 in time-bounded chunks
Ingest historical data into Tiger Cloud hypertable via COPY
Run data validation queries on both systems: row counts by time bucket, aggregate comparisons, spot checks on specific device/dimension combinations
Migrate Grafana dashboards panel-by-panel: update data source, rewrite TQL to PostgreSQL SQL
Run Grafana dashboards against Tiger Cloud data for at least 24 hours before cutting over; compare to Timestream dashboards visually
Disable writes to Timestream via application configuration or feature flag
Verify no active Timestream write calls appearing in application logs
Keep Timestream data in read-only mode for 30 days post-cutover as a rollback buffer
Monitor Tiger Cloud query performance and storage growth for the first week
Enable Hypercore compression on fully ingested historical data chunks
Set up the data retention policy on Tiger Cloud (equivalent to Timestream magnetic store retention)
Document your rollback procedure: if issues arise within the 30-day buffer window, re-enable Timestream writes and diagnose before proceeding
Octave is a cleantech company building analytics infrastructure for second-life batteries. They collect and analyze time-series data from batteries across lifecycle stages, and they were running that workload on AWS Timestream.
Octave migrated to Tiger Data in search of better compression and query performance on historical data at scale. After migration, Octave achieved 26x compression on historical battery telemetry. The migration path they followed matches what this guide describes: export from Timestream, schema translation, ingest into TimescaleDB, and validation against the source data.
For the full technical account, see the Octave case study and the detailed writeup at How Octave Achieves a High Compression Ratio and Speedy Queries on Historical Data.
Octave is not an isolated example. Torus, another Tiger Data customer that migrated from Timestream, reported average response times dropping from 800ms to 70ms after migration. TimescaleDB's automatic partition pruning, chunk exclusion, and Hypercore compression give it a structural speed advantage on time-range queries that Timestream, built on a more generalized storage layer, was not designed to match.
If you are evaluating migration paths before committing to PostgreSQL, start with the AWS Timestream alternatives overview and the best managed time-series databases in 2026 comparison. Both cover the full landscape, including Timestream for InfluxDB, QuestDB, and other options.
If you have decided on the PostgreSQL path, start a Tiger Cloud trial and run through the setup checklist above with a small data sample before committing to the full migration. Tiger Data's support team is available throughout the trial period.
AWS closed LiveAnalytics to new customers in June 2025 and announced end-of-life for the service. The surviving product is Timestream for InfluxDB, which AWS recommends as the default migration path. PostgreSQL on Tiger Cloud is the alternative for teams that need SQL compatibility, higher cardinality support, or the broader PostgreSQL ecosystem.
Some custom work is unavoidable. The export via AWS Data Export to S3 is straightforward, and the PostgreSQL ingest via COPY is standard. The custom work is schema mapping (dimensions to columns) and query rewrites (TQL to SQL). Single-measure record schemas also require a pivot step during ingest to consolidate multiple rows into a single PostgreSQL row per timestamp. A single-table Timestream setup with 3 to 5 dimensions and 2 to 3 measures takes roughly 1 to 3 days for a developer familiar with PostgreSQL. Multi-table setups with complex TQL queries take longer.
In Timestream single-measure records, measure_name is a row-level filter. A query that reads WHERE measure_name = 'temperature' selects which metric you are reading from a generic value column. In PostgreSQL, each distinct measure_name value becomes its own column. The schema mapping section above has the full DDL walkthrough and the pivot approach for handling single-measure exports.
Tiger Cloud is based on PostgreSQL with TimescaleDB, designed for high-ingest time-series workloads. In published benchmarks, TimescaleDB handled significantly higher insert rates than Timestream LiveAnalytics while maintaining faster query performance. Real-world migration results support this: Torus, a Tiger Data customer that migrated from Timestream, reported average query response times dropping from 800ms to 70ms after migration. TimescaleDB's automatic partitioning, Hypercore compression, and chunk exclusion give it a structural speed advantage on time-range queries.
There is no built-in series cardinality limit equivalent to InfluxDB's approximately 10 million series constraint. Cardinality in PostgreSQL is a schema design and indexing concern, not a hard system ceiling. High-cardinality workloads benefit from the index design choices covered in the schema mapping section, but nothing in Tiger Cloud enforces a series count limit. This is one of the reasons engineers with large industrial IoT workloads choose the PostgreSQL path over Timestream for InfluxDB.
Tiger Cloud uses a standard PostgreSQL data source. The built-in Grafana PostgreSQL plugin works without modification — no special Tiger Cloud plugin is required. The PostgreSQL data source has been available in Grafana since v2.1 and as of Grafana 10+ supports all features needed for time-series dashboards, including $__timeFilter, $__timeGroupAlias, and $__interval macros.
A single table with moderate data and a PostgreSQL-familiar team typically finishes in 1 to 2 weeks including validation. Large multi-table setups with significant application-layer query rewrites may take 4 to 8 weeks. The dual-write period should run at least 24 to 72 hours before hard cutover.
Yes. Tiger Cloud operates independently of AWS infrastructure and is accessible over standard TCP/IP from any cloud environment, including AWS-hosted applications. For latency-sensitive applications, select a Tiger Cloud region close to your application's AWS region. Check Tiger Cloud documentation for current network connectivity options, including VPC peering availability for private connectivity requirements.
Yes. Tiger Cloud exposes a standard PostgreSQL wire protocol. Any PostgreSQL-compatible driver — including psycopg2, asyncpg, pgx, pg for Node.js, and JDBC — connects using the standard connection URI. Application SQL query code requires no changes beyond replacing the Timestream SDK calls.
Timestream data is not automatically deleted. Existing tables remain accessible until the LiveAnalytics end-of-life deadline. Keep read access available for at least 30 days post-cutover as a rollback buffer, then archive to S3 before decommissioning. Check AWS Timestream documentation for current end-of-life dates.
Tiger Data does not have a direct magnetic store equivalent. The functional equivalent is a combination of two TimescaleDB features: data retention policies via add_retention_policy(), which automatically drop data older than a specified interval, and Hypercore compression, which reduces storage costs for older data that must be retained. For tiered retention, the standard pattern is continuous aggregates on the raw hypertable plus a retention policy that drops the raw data after a defined window, so the aggregate survives while the raw data ages out.
As of May 2026, Tiger Data does not offer an automated Timestream-to-PostgreSQL migration tool. The migration process requires engineer-executed steps: Timestream export, schema translation, PostgreSQL ingest, and query rewrites. Tiger Data's support team is available during the Tiger Cloud trial period for migration assistance. Check Tiger Cloud documentation for the latest available tooling before starting, since this area moves quickly.