DynamoDB Query a GSI in Node.js (AWS SDK v3)
Querying a global secondary index is a normal Query plus one parameter: IndexName. The key condition then targets the index's keys, not the table's — here AlbumTitle-index lets us fetch songs by album, an access pattern the base table (Artist + SongTitle) can't serve without a scan.
Code
import {DynamoDBClient, QueryCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const items = [];
let lastEvaluatedKey;
do {
const response = await client.send(
new QueryCommand({
TableName: 'Music',
IndexName: 'AlbumTitle-index',
KeyConditionExpression: '#hashKey = :hashKeyValue',
ExpressionAttributeNames: {
'#hashKey': 'AlbumTitle'
},
ExpressionAttributeValues: {
':hashKeyValue': {S: 'Danzon'}
},
ExclusiveStartKey: lastEvaluatedKey
})
);
items.push(...(response.Items ?? []));
lastEvaluatedKey = response.LastEvaluatedKey;
} while (lastEvaluatedKey);
console.log(`Found ${items.length} songs on the album`);Explanation
IndexName— names the GSI to query (TableNameis still required). TheKeyConditionExpressionuses the index's partition (and optional sort) key —AlbumTitlehere — with the same operators as a table query.- Eventual consistency only — GSIs replicate from the base table asynchronously. Passing
ConsistentRead: trueon a GSI query doesn't upgrade it; it fails with aValidationException. (Local secondary indexes do support strong consistency.) - You get projected attributes only — a GSI query returns what the index projects (
ALL,KEYS_ONLY, orINCLUDE-listed attributes) and cannot fetch the rest from the base table. Need an unprojected attribute? Follow up withGetItemon the table key, or widen the projection. - Keys aren't unique in a GSI — many items can share the same index key, and items missing the index key attribute simply don't appear (that's the sparse-index pattern).
- Pagination — identical to a table query: at most 1 MB per page, loop
LastEvaluatedKey→ExclusiveStartKeyuntil it'sundefined.
Do it visually
The DynamoDB Expression Builder builds the key condition + name/value maps for index queries and copies the code.
To browse a table's indexes and run GSI queries from a form — paginated grid, copy the generated SDK v3 code — download DynoTable.
Related examples
- DynamoDB Query a GSI in Python — the same index query with boto3.
- DynamoDB Query a GSI with the AWS CLI — the same index query from the shell.
- DynamoDB Query in Node.js — querying the base table.
- GSI vs. LSI — which index type fits the access pattern.
- Why GSIs are eventually consistent — the replication lag explained.
- "The table does not have the specified index" — the index name doesn't match (GSI names are case-sensitive).
- "Consistent reads are not supported on global secondary indexes" — why the consistent-read flag fails on a GSI.
References
- Query — Amazon DynamoDB API Reference
- Using Global Secondary Indexes in DynamoDB — Amazon DynamoDB Developer Guide
- Paginating table query results — Amazon DynamoDB Developer Guide
Last verified 2026-07-13 against the official AWS documentation linked above.