Pagination, Waiters & Retries
Iterate large result sets, wait for resource state changes, and handle transient failures with exponential backoff and idempotency.
Busca en todas las páginas de la documentación
Iterate large result sets, wait for resource state changes, and handle transient failures with exponential backoff and idempotency.
Iterate every page of a list operation without managing tokens.
# --- Python (boto3) ---
import boto3
s3 = boto3.client("s3")
for page in s3.get_paginator("list_objects_v2").paginate(Bucket="b"):
for obj in page.get("Contents", []):
print(obj["Key"])// --- TypeScript (AWS SDK v3) ---
import { S3Client, paginateListObjectsV2 } from "@aws-sdk/client-s3";
const s3 = new S3Client({});
for await (const page of paginateListObjectsV2({ client: s3 }, { Bucket: "b" })) {
for (const o of page.Contents ?? []) console.log(o.Key);
}Collect all pages into a single array.
# --- Python (boto3) ---
s3 = boto3.client("s3")
paginator = s3.get_paginator("list_objects_v2")
items = []
for page in paginator.paginate(Bucket="b"):
items.extend(page.get("Contents", []))// --- TypeScript (AWS SDK v3) ---
import { paginateListObjectsV2 } from "@aws-sdk/client-s3";
const items = [];
for await (const page of paginateListObjectsV2({ client: s3 }, { Bucket: "b" })) {
items.push(...(page.Contents ?? []));
}Filter results with a JMESPath expression during iteration.
# --- Python (boto3) ---
s3 = boto3.client("s3")
paginator = s3.get_paginator("list_objects_v2")
for obj in paginator.paginate(Bucket="b").search("Contents[?Size > `1000`]"):
print(obj["Key"])// --- TypeScript (AWS SDK v3) ---
// v3 has no built-in JMESPath; filter manually or use a library
for await (const page of paginateListObjectsV2({ client: s3 }, { Bucket: "b" })) {
const large = page.Contents?.filter(o => o.Size && o.Size > 1000) ?? [];
large.forEach(o => console.log(o.Key));
}Control pagination parameters: items per page and total limit.
# --- Python (boto3) ---
s3 = boto3.client("s3")
paginator = s3.get_paginator("list_objects_v2")
for page in paginator.paginate(
Bucket="b",
PaginationConfig={"PageSize": 50, "MaxItems": 200}
):
print(len(page.get("Contents", [])))// --- TypeScript (AWS SDK v3) ---
import { paginateListObjectsV2 } from "@aws-sdk/client-s3";
for await (const page of paginateListObjectsV2(
{ client: s3 },
{ Bucket: "b", MaxKeys: 50 }
)) {
console.log(page.Contents?.length);
}Manually handle pagination tokens when paginators are not available.
# --- Python (boto3) ---
s3 = boto3.client("s3")
token = None
while True:
kwargs = {"Bucket": "b", "MaxKeys": 50}
if token: kwargs["ContinuationToken"] = token
resp = s3.list_objects_v2(**kwargs)
print(len(resp.get("Contents", [])))
if not resp.get("IsTruncated"): break
token = resp.get("NextContinuationToken")// --- TypeScript (AWS SDK v3) ---
import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
const s3 = new S3Client({});
let token: string | undefined;
do {
const resp = await s3.send(new ListObjectsV2Command({ Bucket: "b", MaxKeys: 50, ContinuationToken: token }));
console.log(resp.Contents?.length);
token = resp.NextContinuationToken;
} while (token);Wait for a resource to reach a desired state (e.g., instance running).
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2")
waiter = ec2.get_waiter("instance_running")
waiter.wait(InstanceIds=["i-123456"])
print("Instance is running")// --- TypeScript (AWS SDK v3) ---
import { EC2Client, waitUntilInstanceRunning } from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({});
await waitUntilInstanceRunning({ client: ec2 }, { InstanceIds: ["i-123456"] });
console.log("Instance is running");Override waiter polling intervals and maximum attempts.
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2")
waiter = ec2.get_waiter("instance_running")
waiter.wait(
InstanceIds=["i-123456"],
WaiterConfig={"Delay": 10, "MaxAttempts": 30}
)// --- TypeScript (AWS SDK v3) ---
import { EC2Client, waitUntilInstanceRunning } from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({});
await waitUntilInstanceRunning({ client: ec2, maxWaitTime: 300 }, { InstanceIds: ["i-123456"] });
console.log("Waiter succeeded");Check the outcome of a waiter (SUCCESS, FAILURE, or TIMEOUT).
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2")
try:
waiter = ec2.get_waiter("instance_running")
waiter.wait(InstanceIds=["i-xyz"], WaiterConfig={"MaxAttempts": 5})
except Exception as e:
print(f"Waiter failed: {type(e).__name__}")// --- TypeScript (AWS SDK v3) ---
import { EC2Client, waitUntilInstanceRunning } from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({});
const result = await waitUntilInstanceRunning({ client: ec2 }, { InstanceIds: ["i-xyz"] });
console.log(result.state); // "SUCCESS" | "FAILURE" | "TIMEOUT"Choose retry behavior: standard exponential backoff or adaptive (throttling-aware).
# --- Python (boto3) ---
from botocore.config import Config
import boto3
s3 = boto3.client("s3", config=Config(retries={"mode": "standard"}))
s3_adaptive = boto3.client("s3", config=Config(retries={"mode": "adaptive"}))
resp = s3.get_object(Bucket="b", Key="k")// --- TypeScript (AWS SDK v3) ---
import { S3Client } from "@aws-sdk/client-s3";
const s3Standard = new S3Client({ maxAttempts: 3 });
const s3Adaptive = new S3Client({
maxAttempts: 5,
retryMode: "adaptive"
});Configure the maximum number of retries (including the initial attempt).
# --- Python (boto3) ---
from botocore.config import Config
import boto3
s3 = boto3.client("s3", config=Config(retries={"max_attempts": 10}))
resp = s3.get_object(Bucket="b", Key="k")
print(resp["Body"].read().decode())// --- TypeScript (AWS SDK v3) ---
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({ maxAttempts: 10 });
const resp = await s3.send(new GetObjectCommand({ Bucket: "b", Key: "k" }));Define a retry strategy with custom backoff logic.
# --- Python (boto3) ---
from botocore.config import Config
import boto3
cfg = Config(retries={"mode": "adaptive", "max_attempts": 15})
s3 = boto3.client("s3", config=cfg)// --- TypeScript (AWS SDK v3) ---
import { S3Client } from "@aws-sdk/client-s3";
import { ConfiguredRetryStrategy } from "@aws-sdk/util-retry";
const s3 = new S3Client({
retryStrategy: new ConfiguredRetryStrategy(15, (attempt) => Math.pow(2, attempt) * 100)
});Catch throttling exceptions and implement custom backoff logic.
# --- Python (boto3) ---
import boto3
from botocore.exceptions import ClientError
s3 = boto3.client("s3")
try:
resp = s3.get_object(Bucket="b", Key="k")
except ClientError as e:
if e.response["Error"]["Code"] == "ThrottlingException":
print("Rate limited; retry after backoff")// --- TypeScript (AWS SDK v3) ---
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { ThrottlingException } from "@aws-sdk/client-s3";
const s3 = new S3Client({});
try {
await s3.send(new GetObjectCommand({ Bucket: "b", Key: "k" }));
} catch (err) {
if (err instanceof ThrottlingException) console.log("Throttled; implement backoff");
}Include a unique token to ensure a request is idempotent if retried.
# --- Python (boto3) ---
import boto3
import uuid
dynamodb = boto3.client("dynamodb")
resp = dynamodb.put_item(
TableName="t",
Item={"id": {"S": "123"}},
ClientRequestToken=str(uuid.uuid4())
)// --- TypeScript (AWS SDK v3) ---
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";
import { randomUUID } from "crypto";
const db = new DynamoDBClient({});
await db.send(new PutItemCommand({
TableName: "t",
Item: { id: { S: "123" } },
ClientRequestToken: randomUUID()
}));Implement manual retry loop with randomized delays to avoid thundering herd.
# --- Python (boto3) ---
import time
import random
import boto3
s3 = boto3.client("s3")
for attempt in range(1, 6):
try:
resp = s3.get_object(Bucket="b", Key="k")
break
except Exception:
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)// --- TypeScript (AWS SDK v3) ---
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({});
for (let attempt = 1; attempt <= 5; attempt++) {
try {
await s3.send(new GetObjectCommand({ Bucket: "b", Key: "k" }));
break;
} catch (err) {
const wait = Math.pow(2, attempt) + Math.random();
await new Promise(r => setTimeout(r, wait * 1000));
}
}Limit the number of concurrent requests to avoid overwhelming the network or API.
# --- Python (boto3) ---
from concurrent.futures import ThreadPoolExecutor
import boto3
s3 = boto3.client("s3")
keys = ["k1", "k2", "k3", "k4", "k5"]
with ThreadPoolExecutor(max_workers=2) as executor:
results = list(executor.map(lambda k: s3.get_object(Bucket="b", Key=k), keys))// --- TypeScript (AWS SDK v3) ---
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
const keys = ["k1", "k2", "k3", "k4", "k5"];
const results = [];
for (let i = 0; i < keys.length; i += 2) {
const chunk = keys.slice(i, i + 2);
const promises = chunk.map(k => s3.send(new GetObjectCommand({ Bucket: "b", Key: k })));
results.push(...await Promise.all(promises));
}Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última actualización: 23 jul 2026