Ravindra BagaleCourses & study guides मराठी Track your progress

DynamoDB CRUD, Query, Scan, GSI and TTL Step by Step

In What Is Amazon DynamoDB? you made a table and learned keys. Now you do real work: Put, Get, Query vs Scan, GSI and LSI, TTL, Streams and backups — with code in Python, Node.js, Java and PHP.

What you'll learn in this chapter

  • PutItem and GetItem
  • Query vs Scan and cost
  • GSI and LSI
  • TTL, Streams, backups
  • Code samples in four languages

1. A story: find orders by email without scanning the world

Orders table PK is orderId. Support asks: show all orders for rita@mail.test. A Scan of every order works for 50 rows and dies at 5 million. The fix is a Global Secondary Index with PK email and SK createdAt, then a Query.

2. CRUD basics

What is it?

  • PutItem — create or replace a whole item.
  • GetItem — read by full primary key (PK + SK if you have one).
  • UpdateItem — change some attributes.
  • DeleteItem — remove by key.
  • Query — all items under one PK (optional SK condition). Uses indexes efficiently.
  • Scan — walk the table or index; filter after read. Costs for every item examined.

Why Scan costs more: billing for reads is based on data examined, not only data returned. A filter that throws away 99% still charged you for reading it.

3. GSI vs LSI

GSI (Global Secondary Index)LSI (Local Secondary Index)
KeysPK and SK can both differ from the tableSame PK as table, different SK
CapacityOwn throughput (or on-demand)Shares the table's capacity
Size limit per PKNone special beyond table rules10 GB per partition key value
WhenNew access pattern with a different PKSame PK, sort another attribute
Count limitsUp to 20 GSIs per table (default quota)Up to 5 LSIs; only at table creation

4. TTL, Streams and backups

  • TTL: an attribute holding a Unix epoch second. When time passes, DynamoDB deletes the item for free in the background. Great for sessions and temp links.
  • Streams: a time-ordered log of item changes. Lambda can process inserts/updates/deletes (sync search index, drive workflows).
  • Backups: on-demand backup or point-in-time recovery (PITR) for restore. Turn PITR on for important tables.

5. Code: Put and Query

Python (boto3)

import boto3
from boto3.dynamodb.conditions import Key
table = boto3.resource("dynamodb", region_name="ap-south-1").Table("OrdersLab")
table.put_item(Item={"orderId": "O1", "email": "rita@mail.test", "total": 499})
# After GSI EmailIndex (PK email, SK orderId):
r = table.query(IndexName="EmailIndex", KeyConditionExpression=Key("email").eq("rita@mail.test"))
print(r["Items"])

Node.js (@aws-sdk/client-dynamodb)

import { DynamoDBClient, PutItemCommand, QueryCommand } from "@aws-sdk/client-dynamodb";
const c = new DynamoDBClient({ region: "ap-south-1" });
await c.send(new PutItemCommand({ TableName: "OrdersLab",
  Item: { orderId: { S: "O1" }, email: { S: "rita@mail.test" }, total: { N: "499" } } }));
const q = await c.send(new QueryCommand({ TableName: "OrdersLab", IndexName: "EmailIndex",
  KeyConditionExpression: "email = :e", ExpressionAttributeValues: { ":e": { S: "rita@mail.test" } } }));
console.log(q.Items);

Java (AWS SDK v2)

DynamoDbClient ddb = DynamoDbClient.builder().region(Region.AP_SOUTH_1).build();
ddb.putItem(PutItemRequest.builder().tableName("OrdersLab")
  .item(Map.of("orderId", AttributeValue.fromS("O1"),
               "email", AttributeValue.fromS("rita@mail.test"),
               "total", AttributeValue.fromN("499"))).build());

PHP (AWS SDK for PHP)

$ddb = new Aws\DynamoDb\DynamoDbClient(['region'=>'ap-south-1','version'=>'latest']);
$ddb->putItem(['TableName'=>'OrdersLab','Item'=>[
  'orderId'=>['S'=>'O1'], 'email'=>['S'=>'rita@mail.test'], 'total'=>['N'=>'499']
]]);

6. Lab: Query, GSI and TTL

How to do it (step by step)

  1. Create table OrdersLab, PK orderId (S), on-demand.
  2. Put three items with different orderId and emails (console or CLI).
  3. Indexes → Create index → GSI name EmailIndex, PK email (S), SK orderId (S), on-demand → Create. Wait until Active.
  4. Query on EmailIndex with one email — only that user's orders. Compare a Scan with a filter on email — works, but note Consumed capacity is higher on large tables.
  5. Additional settings → TTL → enable attribute expiresAt. Put an item with expiresAt = now+120 (epoch seconds). After a few minutes it disappears (TTL is eventually processed, not instant).
  6. Backups → Edit PITR → On (optional for lab).

Cleanup

  1. Delete table OrdersLab (deletes GSIs). Turn off PITR first if prompted.

7. Interview questions

Q. Query vs Scan?

Query reads items for one PK (efficient). Scan reads the table/index then filters (costly at scale).

Q. When GSI?

When you need to Query with a partition key that is not the table PK.

Q. When LSI?

Same PK, different sort attribute; must be defined at table creation; 10 GB per PK.

Q. What is TTL?

An epoch-seconds attribute; DynamoDB deletes expired items in the background at no extra write cost.

Q. Why Streams + Lambda?

React to every change — sync OpenSearch, send email, update aggregates — without polling.

Try at home

  1. Add a GSI on AttendanceLab for date as PK and studentId as SK; query who was present on one day.
  2. From Python or Node, PutItem five orders and Query by email.

In short

  1. Put/Get/Update/Delete by key; Query by PK; avoid Scan on big tables.
  2. GSI = new PK/SK; LSI = same PK, new SK at create time.
  3. TTL auto-expires; Streams feed Lambda; PITR saves you.
  4. Same SDK ideas in Python, Node, Java, PHP.

Practice Tasks

About this scenario

Cape Town Safaris is a tourism business in Cape Town. Thabo Nkosi looks after its IT and cloud work. They count money in ZAR and run their AWS resources in the af-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 11

Easy Describe a table

Why: See the keys, indexes, item count and status of a table.

What to do: Describe table capetownsafari-orders.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Easy Scan a small table

Why: Scan is fine for tiny tables or one-off checks; avoid it on big ones.

What to do: Scan the table capetownsafari-settings.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Get one item by key

Why: GetItem is the fastest read: one item by its full key.

What to do: Get the item with orderId "o-101" from capetownsafari-orders.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Put an item

Why: DynamoDB JSON shows the type of each value: S for string, N for number.

What to do: Put an item into capetownsafari-orders with orderId "o-101" (string) and amount 2500 (number).

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium CloudFormation: on-demand table

Why: On-demand tables need no capacity planning.

What to do: Template with a DynamoDB table capetownsafari-orders, partition key orderId (String), billing mode PAY_PER_REQUEST.

How:
  1. Start from the top-level keys the task names.
  2. Indent child keys with 2 spaces (no tabs).
  3. Fill in each property with the value from the task.
  4. Click Check answer. Key order does not matter.

Medium Lambda access to one table

Why: The function only needs to read and write items in its own table.

What to do: Allow dynamodb:GetItem, dynamodb:PutItem, dynamodb:Query on arn:aws:dynamodb:af-south-1:122836786824:table/capetownsafari-orders only.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Medium Delete one item

Why: Delete by the full primary key.

What to do: Delete the item with orderId "o-099" from capetownsafari-orders.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Read capacity units

Why: Provisioned tables need the right RCU.

What to do: Strongly consistent reads of 6 KB items, 10 reads per second. How many RCUs?

How:
  1. Write down the numbers the task gives you.
  2. Work it out step by step on paper.
  3. Type only the final answer in the box.
  4. Click Check answer.

Hard Create a DynamoDB table

Why: On-demand billing means you pay per request, with no capacity to plan.

What to do: Create table capetownsafari-orders with partition key orderId (string), on-demand billing.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Query by partition key

Why: Query reads only matching items, unlike Scan which reads the whole table.

What to do: Query table capetownsafari-payments for customerId = "c-77" using the expression customerId = :c.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Turn on TTL

Why: TTL deletes expired items for free, e.g. OTPs or sessions.

What to do: Enable TTL on table capetownsafari-otp using the attribute expiresAt.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Revision, comparison and interview cards

Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.

Revision card: Put, Get, Update, Delete. APIs need create/read/update/delete without a SQL server. PutItem, GetItem, UpdateItem, DeleteItem use the primary key. IAM allow those actions on table ARN; call from Lambda with SDK. POST creates noteId; GET returns it; DELETE removes it.
Revision card: Put, Get, Update, Delete · Download PNG · Open card page
Revision card: Query vs Scan. Scan feels easy and becomes a bill shock. Query uses PK (and optional SK). Scan reads the table; you pay for examined items. Always design a key that lets you Query. Use Scan only for tiny labs or rare admin jobs. List notes for user 7 → Query PK=7. Scan whole table → expensive.
Revision card: Query vs Scan · Download PNG · Open card page
Revision card: GSI and LSI. A second access pattern appears after launch. GSI = new PK/SK for Queries. LSI = same PK, different SK; created with the table. Add GSI email-index; Query by email without Scan. Find user by email for login → GSI on email.
Revision card: GSI and LSI · Download PNG · Open card page
Revision card: TTL, Streams and backups. Old sessions and change feeds need automation, not cron on EC2. TTL expires items by epoch seconds. Streams feed Lambda on changes. PITR backups. Enable TTL on attribute expiresAt; enable Streams → new Lambda. Magic-link tokens vanish after 15 minutes via TTL.
Revision card: TTL, Streams and backups · Download PNG · Open card page
Comparison: Query vs Scan. Query: Items for one partition key (optional sort range). Scan: Potentially the whole table.
Comparison: Query vs Scan · Download PNG · Open card page
Comparison: GSI vs LSI. GSI: New partition key (and optional sort key). LSI: Same partition key, different sort key.
Comparison: GSI vs LSI · Download PNG · Open card page
Comparison: PutItem vs UpdateItem. PutItem: Writes a full item (replaces if same key). UpdateItem: Changes only the attributes you name.
Comparison: PutItem vs UpdateItem · Download PNG · Open card page
Comparison: TTL expiry vs DeleteItem. TTL expiry: DynamoDB removes expired items in the background. DeleteItem: Your code deletes immediately by key.
Comparison: TTL expiry vs DeleteItem · Download PNG · Open card page
Interview card: Why can Scan cost more than Query?. You pay for items examined, not only items returned. Filters run after read, so they do not save RCU the way keys do. 10 GB table Scan to find 3 rows still reads ~10 GB.
Interview card: Why can Scan cost more than Query? · Download PNG · Open card page
Interview card: What problem does a GSI solve?. Querying by an attribute that is not the table's primary key. Avoids Scan for a second access pattern. Orders by orderId; GSI by customerId+createdAt for "my orders".
Interview card: What problem does a GSI solve? · Download PNG · Open card page
Interview card: How does DynamoDB TTL work?. Number attribute with Unix epoch seconds; expired items are deleted later in the background. Not a precise alarm clock — deletion is eventually done. Set expiresAt = now+900 for 15-minute tokens.
Interview card: How does DynamoDB TTL work? · Download PNG · Open card page
Interview card: What are DynamoDB Streams used for?. Change data capture: Lambda reacts to inserts/updates/deletes. Fan out search index updates, audit logs, or sync. New note → Stream → Lambda writes to OpenSearch.
Interview card: What are DynamoDB Streams used for? · Download PNG · Open card page

More cards: Ravi Sir's Cards.