Create AWS Timestream Tables

The aws:timestreamwrite/table:Table resource, part of the Pulumi AWS provider, defines a Timestream table within a database: its name, retention policies, and optional partitioning schema. This guide focuses on two capabilities: retention configuration (default and custom) and custom partition keys for query optimization.

Timestream tables belong to Timestream databases that must exist before table creation. The examples are intentionally small. Combine them with your own database resources and ingestion pipelines.

Create a table with default retention

Most deployments start by creating a table with AWS-managed retention defaults.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.timestreamwrite.Table("example", {
    databaseName: exampleAwsTimestreamwriteDatabase.databaseName,
    tableName: "example",
});
import pulumi
import pulumi_aws as aws

example = aws.timestreamwrite.Table("example",
    database_name=example_aws_timestreamwrite_database["databaseName"],
    table_name="example")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/timestreamwrite"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := timestreamwrite.NewTable(ctx, "example", &timestreamwrite.TableArgs{
			DatabaseName: pulumi.Any(exampleAwsTimestreamwriteDatabase.DatabaseName),
			TableName:    pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.TimestreamWrite.Table("example", new()
    {
        DatabaseName = exampleAwsTimestreamwriteDatabase.DatabaseName,
        TableName = "example",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.timestreamwrite.Table;
import com.pulumi.aws.timestreamwrite.TableArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Table("example", TableArgs.builder()
            .databaseName(exampleAwsTimestreamwriteDatabase.databaseName())
            .tableName("example")
            .build());

    }
}
resources:
  example:
    type: aws:timestreamwrite:Table
    properties:
      databaseName: ${exampleAwsTimestreamwriteDatabase.databaseName}
      tableName: example

The databaseName property references an existing Timestream database. The tableName property sets the table’s identifier. Without explicit retentionProperties, Timestream uses defaults: 73,000 days (200 years) for magnetic storage and 6 hours for memory storage.

Configure custom retention periods and tags

Applications with specific cost or compliance requirements control how long data remains in fast memory storage versus cheaper magnetic storage.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.timestreamwrite.Table("example", {
    databaseName: exampleAwsTimestreamwriteDatabase.databaseName,
    tableName: "example",
    retentionProperties: {
        magneticStoreRetentionPeriodInDays: 30,
        memoryStoreRetentionPeriodInHours: 8,
    },
    tags: {
        Name: "example-timestream-table",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.timestreamwrite.Table("example",
    database_name=example_aws_timestreamwrite_database["databaseName"],
    table_name="example",
    retention_properties={
        "magnetic_store_retention_period_in_days": 30,
        "memory_store_retention_period_in_hours": 8,
    },
    tags={
        "Name": "example-timestream-table",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/timestreamwrite"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := timestreamwrite.NewTable(ctx, "example", &timestreamwrite.TableArgs{
			DatabaseName: pulumi.Any(exampleAwsTimestreamwriteDatabase.DatabaseName),
			TableName:    pulumi.String("example"),
			RetentionProperties: &timestreamwrite.TableRetentionPropertiesArgs{
				MagneticStoreRetentionPeriodInDays: pulumi.Int(30),
				MemoryStoreRetentionPeriodInHours:  pulumi.Int(8),
			},
			Tags: pulumi.StringMap{
				"Name": pulumi.String("example-timestream-table"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.TimestreamWrite.Table("example", new()
    {
        DatabaseName = exampleAwsTimestreamwriteDatabase.DatabaseName,
        TableName = "example",
        RetentionProperties = new Aws.TimestreamWrite.Inputs.TableRetentionPropertiesArgs
        {
            MagneticStoreRetentionPeriodInDays = 30,
            MemoryStoreRetentionPeriodInHours = 8,
        },
        Tags = 
        {
            { "Name", "example-timestream-table" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.timestreamwrite.Table;
import com.pulumi.aws.timestreamwrite.TableArgs;
import com.pulumi.aws.timestreamwrite.inputs.TableRetentionPropertiesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Table("example", TableArgs.builder()
            .databaseName(exampleAwsTimestreamwriteDatabase.databaseName())
            .tableName("example")
            .retentionProperties(TableRetentionPropertiesArgs.builder()
                .magneticStoreRetentionPeriodInDays(30)
                .memoryStoreRetentionPeriodInHours(8)
                .build())
            .tags(Map.of("Name", "example-timestream-table"))
            .build());

    }
}
resources:
  example:
    type: aws:timestreamwrite:Table
    properties:
      databaseName: ${exampleAwsTimestreamwriteDatabase.databaseName}
      tableName: example
      retentionProperties:
        magneticStoreRetentionPeriodInDays: 30
        memoryStoreRetentionPeriodInHours: 8
      tags:
        Name: example-timestream-table

The retentionProperties block defines two storage tiers. The memoryStoreRetentionPeriodInHours controls how long recent data stays in fast, expensive memory (8 hours here). After that window, data moves to magneticStoreRetentionPeriodInDays (30 days here), which is slower but cheaper. Queries against memory storage are faster; queries against magnetic storage cost less but take longer.

Define a custom partition key for query optimization

High-cardinality workloads benefit from custom partition keys that align with query patterns.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.timestreamwrite.Table("example", {
    databaseName: exampleAwsTimestreamwriteDatabase.databaseName,
    tableName: "example",
    schema: {
        compositePartitionKey: {
            enforcementInRecord: "REQUIRED",
            name: "attr1",
            type: "DIMENSION",
        },
    },
});
import pulumi
import pulumi_aws as aws

example = aws.timestreamwrite.Table("example",
    database_name=example_aws_timestreamwrite_database["databaseName"],
    table_name="example",
    schema={
        "composite_partition_key": {
            "enforcement_in_record": "REQUIRED",
            "name": "attr1",
            "type": "DIMENSION",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/timestreamwrite"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := timestreamwrite.NewTable(ctx, "example", &timestreamwrite.TableArgs{
			DatabaseName: pulumi.Any(exampleAwsTimestreamwriteDatabase.DatabaseName),
			TableName:    pulumi.String("example"),
			Schema: &timestreamwrite.TableSchemaArgs{
				CompositePartitionKey: &timestreamwrite.TableSchemaCompositePartitionKeyArgs{
					EnforcementInRecord: pulumi.String("REQUIRED"),
					Name:                pulumi.String("attr1"),
					Type:                pulumi.String("DIMENSION"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.TimestreamWrite.Table("example", new()
    {
        DatabaseName = exampleAwsTimestreamwriteDatabase.DatabaseName,
        TableName = "example",
        Schema = new Aws.TimestreamWrite.Inputs.TableSchemaArgs
        {
            CompositePartitionKey = new Aws.TimestreamWrite.Inputs.TableSchemaCompositePartitionKeyArgs
            {
                EnforcementInRecord = "REQUIRED",
                Name = "attr1",
                Type = "DIMENSION",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.timestreamwrite.Table;
import com.pulumi.aws.timestreamwrite.TableArgs;
import com.pulumi.aws.timestreamwrite.inputs.TableSchemaArgs;
import com.pulumi.aws.timestreamwrite.inputs.TableSchemaCompositePartitionKeyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Table("example", TableArgs.builder()
            .databaseName(exampleAwsTimestreamwriteDatabase.databaseName())
            .tableName("example")
            .schema(TableSchemaArgs.builder()
                .compositePartitionKey(TableSchemaCompositePartitionKeyArgs.builder()
                    .enforcementInRecord("REQUIRED")
                    .name("attr1")
                    .type("DIMENSION")
                    .build())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:timestreamwrite:Table
    properties:
      databaseName: ${exampleAwsTimestreamwriteDatabase.databaseName}
      tableName: example
      schema:
        compositePartitionKey:
          enforcementInRecord: REQUIRED
          name: attr1
          type: DIMENSION

The schema block defines a compositePartitionKey that Timestream uses to organize data physically. The type property specifies whether the key comes from a DIMENSION (metadata attribute) or MEASURE (time-series value). The enforcementInRecord property set to REQUIRED means every ingested record must include the attr1 dimension. Queries filtering on attr1 scan less data, improving performance and reducing costs.

Beyond these examples

These snippets focus on specific table-level features: table creation and naming, retention tier configuration, and custom partition keys. They’re intentionally minimal rather than full time-series solutions.

The examples reference pre-existing infrastructure such as Timestream databases (databaseName references). They focus on configuring the table rather than provisioning the surrounding database or ingestion infrastructure.

To keep things focused, common table patterns are omitted, including:

  • Magnetic store write properties (magneticStoreWriteProperties)
  • Multi-attribute composite partition keys
  • Schema enforcement modes beyond REQUIRED

These omissions are intentional: the goal is to illustrate how each table feature is wired, not provide drop-in time-series modules. See the Timestream Table resource reference for all available configuration options.

Let's create AWS Timestream Tables

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Immutability
What properties can't I change after creating a Timestream table?
The databaseName, tableName, and schema properties are immutable. Changing any of these forces table replacement.
What are the default retention periods for Timestream tables?
If not specified, magneticStoreRetentionPeriodInDays defaults to 73000 days (~200 years) and memoryStoreRetentionPeriodInHours defaults to 6 hours.
Advanced Features
How do I configure a custom partition key for my table?
Use the schema.compositePartitionKey property with enforcementInRecord, name, and type fields. For example, set type to DIMENSION and enforcementInRecord to REQUIRED.
Import & Migration
How do I import an existing Timestream table into Pulumi?
Use the format tableName:databaseName with the import command. For example: pulumi import aws:timestreamwrite/table:Table example ExampleTable:ExampleDatabase.

Using a different cloud?

Explore database guides for other cloud providers: