Skip to content
GitHub Discord

DynamoDB composite keys

Create a DynamoDB table with multi-attribute composite keys in a global secondary index.

sst.config.ts
const table = new sst.aws.Dynamo("MyTable", {
fields: {
userId: "string",
noteId: "string",
region: "string",
category: "string",
createdAt: "number",
},
primaryIndex: { hashKey: "userId", rangeKey: "noteId" },
globalIndexes: {
RegionCategoryIndex: {
hashKey: ["region", "category"],
rangeKey: "createdAt",
},
},
});
const creator = new sst.aws.Function("MyCreator", {
handler: "creator.handler",
link: [table],
url: true,
});
const reader = new sst.aws.Function("MyReader", {
handler: "reader.handler",
link: [table],
url: true,
});
creator.ts
import { Resource } from "sst";
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";
const client = new DynamoDBClient();
export const handler = async () => {
await client.send(
new PutItemCommand({
TableName: Resource.MyTable.name,
Item: {
userId: { S: "user1" },
noteId: { S: Date.now().toString() },
region: { S: "us-east" },
category: { S: "notes" },
createdAt: { N: Date.now().toString() },
},
})
);
return {
statusCode: 200,
body: JSON.stringify({ status: "sent" }, null, 2),
};
};
reader.ts
import { Resource } from "sst";
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
const client = new DynamoDBClient();
export const handler = async () => {
const result = await client.send(
new QueryCommand({
TableName: Resource.MyTable.name,
IndexName: "RegionCategoryIndex",
KeyConditionExpression: "#r = :region AND #c = :category",
ExpressionAttributeNames: {
"#r": "region",
"#c": "category",
},
ExpressionAttributeValues: {
":region": { S: "us-east" },
":category": { S: "notes" },
},
})
);
return {
statusCode: 200,
body: JSON.stringify(result.Items, null, 2),
};
};

View the full example.