DynamoDB Query a GSI with the AWS CLI
Querying a global secondary index is a normal aws dynamodb query plus one flag: --index-name. 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
aws dynamodb query \
--table-name 'Music' \
--index-name 'AlbumTitle-index' \
--key-condition-expression '#hashKey = :hashKeyValue' \
--expression-attribute-names '{"#hashKey":"AlbumTitle"}' \
--expression-attribute-values '{":hashKeyValue":{"S":"Danzon"}}'The output is the matching items in DynamoDB JSON:
{
"Items": [
{"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}, ...}
],
"Count": 2,
"ScannedCount": 2
}Explanation
The base table is billed nothing for this query. Add --return-consumed-capacity INDEXES and the split is explicit:
"ConsumedCapacity": {
"CapacityUnits": 132.0,
"Table": {"CapacityUnits": 0.0},
"GlobalSecondaryIndexes": {"AlbumTitle-index": {"CapacityUnits": 132.0}}
}Zero against the table, everything against the index. A GSI is a separate table with its own key schema, its own partitions and its own capacity, and reading it never touches the base table. That is also why a GSI has its own throttling story: a throttled GSI can throttle base-table writes even though reads never cross over.
--consistent-read is rejected, not downgraded. GSIs replicate asynchronously and there is no flag that changes it:
aws: [ERROR]: An error occurred (ValidationException) when calling the Query operation: Consistent reads are not supported on global secondary indexesExit code 254. The API reference says the same in advance: "Strongly consistent reads are not supported on global secondary indexes. If you query a global secondary index with ConsistentRead set to true, you will receive a ValidationException" (fetched 2026-07-28). Local secondary indexes do accept it, which is one of the few real reasons to pick an LSI. The lag itself is covered in why GSIs are eventually consistent.
Items without the index key are simply not in the index. Counted on the same table: 35 items in the base table, 32 in AlbumTitle-index. The three missing ones have no AlbumTitle attribute at all, confirmed with a scan on attribute_not_exists(AlbumTitle). Nothing errored and nothing warned. This is the sparse index pattern, and it is deliberate design when you write the flag attribute only for the rows you want indexed, and a silent data-loss bug when you assume the index mirrors the table.
You only get what the index projects. "If you query or scan a global secondary index, you can only request attributes that are projected into the index. Global secondary index queries cannot fetch attributes from the parent table" (fetched 2026-07-28). On a KEYS_ONLY or INCLUDE index that means a second get-item per result to fill in the rest, which is the N+1 you were trying to avoid. The projection is fixed when the index is created and cannot be changed afterwards; see index projections before you pick one.
Index keys are not unique. Many items can share one AlbumTitle, so a GSI query returns a collection where the equivalent table query would return one item. There is no such thing as a get-item against a GSI, for exactly this reason.
Pagination behaves as it does on any table query, including the CLI's habit of reporting one page's ConsumedCapacity for an auto-paginated result. That is measured in detail on Query with the AWS CLI; the flags are the same here.
Do it visually
An index query has more moving parts than a table one: the right index, the index's own key names, and a projection that may not carry the attributes you need. The free DynamoDB Query Builder lets you pick the index, builds the key condition against its keys, and emits the CLI command.
To see which indexes a table actually has and query them against your own data — projections listed, a grid that pages as you scroll, copy the request back out as a CLI command — download DynoTable.
Related examples
- DynamoDB Query a GSI in Node.js — the same index query with AWS SDK v3.
- DynamoDB Query a GSI in Python — the same index query with boto3.
- GSI vs. LSI — which index type fits the access pattern.
- "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
- query — AWS CLI Command Reference
- Using Global Secondary Indexes in DynamoDB — Amazon DynamoDB Developer Guide
- Using AWS CLI pagination options — AWS CLI User Guide
Reproduced 2026-07-28 with aws-cli/2.36.9 against DynamoDB Local (amazon/dynamodb-local) on port 9000, on a Music table with an AlbumTitle-index projecting ALL. The error text, the capacity split and the item counts are captured output.