Most DVA-C02 study guides march service by service — Lambda, DynamoDB, S3, API Gateway — and that’s necessary, but it hides a whole category of questions that don’t belong to any single service. The exam repeatedly asks how you interact with AWS in code: where the SDK finds credentials, what happens when a call gets throttled, how you page through thousands of results, and how you hand a client temporary access to an S3 object without proxying the bytes yourself. These are the mechanics of the Development with AWS Services domain — the largest slice of the exam at roughly 32% — and they’re the questions that separate people who’ve actually written AWS code from people who’ve only memorised service names.
This guide is deliberately service-agnostic. It’s the connective tissue that sits underneath the serverless services guide and the DynamoDB deep dive: the SDK behaviours you’re expected to know regardless of which service you’re calling. Master these and a surprising number of “scenario” questions become trivial.
The Default Credential Provider Chain
The first thing any AWS SDK does when you make a call is figure out who you are. It does this by walking an ordered list of sources and using the first one that yields credentials. The exam loves questions of the form “an application works on the developer’s laptop but fails with an access-denied error on EC2” — and the answer is almost always about this chain.
The default order the SDK searches (v2/v3 SDKs, conceptually the same across languages):
| Order | Source | Typical use |
|---|---|---|
| 1 | Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) | Local scripts, CI |
| 2 | Shared config/credentials files (~/.aws/credentials, profiles) | Local development |
| 3 | Web identity / SSO token | Federated & container workloads |
| 4 | ECS container credentials / EKS IRSA (IAM Roles for Service Accounts) | Containers on ECS/EKS |
| 5 | EC2 Instance Metadata Service (IMDS) — the instance’s IAM role | Apps running on EC2 |
The exam’s core lesson: on AWS compute, you should not ship access keys at all. You attach an IAM role — an instance profile on EC2, a task role on ECS, IRSA on EKS — and the SDK picks up temporary, auto-rotating credentials from the metadata service or container endpoint automatically. Hardcoded long-lived keys in code or environment variables are the wrong answer to virtually every DVA-C02 credentials question. If a question describes credentials stored in source control or baked into an AMI, the “correct” remediation is an IAM role plus, where secrets are genuinely needed, Secrets Manager or SSM Parameter Store — which ties into the security guide.
import boto3
# No keys in code. The SDK resolves credentials via the provider chain.
# On EC2/ECS/EKS this transparently uses the attached IAM role.
s3 = boto3.client("s3", region_name="us-east-1")
s3.list_buckets()
A subtle favourite: the SDK also needs a region. If it can’t find one (env var AWS_REGION, a profile setting, or an explicit parameter), the call fails before it ever leaves the machine. “Works locally, fails in the pipeline” is sometimes a missing region, not missing credentials.
Retries, Throttling, and Exponential Backoff
AWS APIs are shared, rate-limited services. When you exceed a service’s request rate you get throttled — a ThrottlingException, ProvisionedThroughputExceededException (DynamoDB), RequestLimitExceeded, or an HTTP 429/503. The exam expects you to know how a well-behaved client responds: retry with exponential backoff, plus jitter.
What exponential backoff means
Instead of retrying immediately (which just adds to the stampede), you wait progressively longer between attempts — 1s, 2s, 4s, 8s… doubling each time up to a cap. Jitter adds a random component to that wait so that a fleet of clients that were all throttled at the same instant don’t all retry at the same instant and re-collide. Backoff spreads retries over time; jitter spreads them across clients.
import random, time
import botocore.exceptions
def call_with_backoff(fn, max_attempts=5, base=0.5, cap=20):
for attempt in range(max_attempts):
try:
return fn()
except botocore.exceptions.ClientError as e:
code = e.response["Error"]["Code"]
transient = code in ("ThrottlingException",
"ProvisionedThroughputExceededException",
"RequestLimitExceeded")
if not transient or attempt == max_attempts - 1:
raise
# exponential backoff with full jitter
delay = min(cap, base * (2 ** attempt))
time.sleep(random.uniform(0, delay))
Two things the exam wants you to internalise:
- The AWS SDKs already do this for you. Every modern SDK has a built-in retry mechanism with configurable modes —
legacy,standard, andadaptive.standardretries a sensible set of transient errors with backoff;adaptiveadditionally uses client-side rate limiting to slow down proactively when it detects throttling. You configuremax_attemptsand the retry mode; you rarely hand-roll the loop in production. But you must recognise the pattern in a question. - Backoff is the fix for throttling, not a bigger instance. When a scenario shows a burst of
ThrottlingExceptions or DynamoDBProvisionedThroughputExceedederrors, the exam-correct application-side answer is “implement exponential backoff and retry” (and, for DynamoDB specifically, consider on-demand capacity or higher provisioned throughput). Scaling compute does nothing for API-level throttling.
| Retry mode | Behaviour |
|---|---|
legacy | Older default, limited retry conditions |
standard | Consistent transient-error retries with exponential backoff across SDKs |
adaptive | standard plus client-side rate limiting that reacts to throttling (use with care) |
Pagination: Don’t Trust the First Page
AWS APIs cap how many items a single response returns — ListObjectsV2 returns up to 1,000 keys, Scan/Query in DynamoDB return up to 1 MB of data, and so on. If you read only the first response, you silently miss data. The exam tests whether you know to follow the continuation token until it’s exhausted.
The mechanic: a truncated response includes a token (NextToken, NextContinuationToken, or DynamoDB’s LastEvaluatedKey). You feed it back into the next request. When the response comes back without one, you’ve reached the end.
# Manual pagination with a continuation token
keys, token = [], None
while True:
kwargs = {"Bucket": "reports"}
if token:
kwargs["ContinuationToken"] = token
resp = s3.list_objects_v2(**kwargs)
keys += [o["Key"] for o in resp.get("Contents", [])]
if not resp.get("IsTruncated"):
break
token = resp["NextContinuationToken"]
Better still, the SDKs provide paginators that hide the token bookkeeping entirely:
paginator = s3.get_paginator("list_objects_v2")
for page in paginator.paginate(Bucket="reports"):
for obj in page.get("Contents", []):
print(obj["Key"])
For DynamoDB, the equivalent signal is LastEvaluatedKey — pass it back as ExclusiveStartKey to continue a Scan or Query. A question describing “the report only shows some of the records” or “results are incomplete for large tables” is almost always a pagination bug. This overlaps directly with the DynamoDB deep dive, where pagination and the 1 MB limit come up again.
Presigned URLs: Delegated, Time-Limited Access
Presigned URLs are one of the most heavily tested S3 concepts on the DVA-C02, precisely because they solve a real developer problem elegantly. A presigned URL grants temporary permission to perform a specific S3 operation (usually GetObject or PutObject) on a specific object, without the requester needing AWS credentials of their own. Your backend — which does have credentials — signs the URL, and the holder can use it until it expires.
Why it matters:
- Uploads and downloads bypass your application server. The client talks to S3 directly using the presigned URL, so you don’t proxy large files through your compute. This is the standard answer to “how do I let users upload large files without overloading my API/Lambda?”
- Access is scoped and temporary. The URL is valid only for the operation, object, and expiry you signed it with. You never expose your bucket publicly or hand out IAM credentials.
- The signer’s permissions bound the URL. A presigned URL can only do what the identity that signed it is allowed to do. If your Lambda’s role can’t
PutObject, the presigned upload URL it generates won’t work either.
# Backend generates a URL the browser can PUT to directly
url = s3.generate_presigned_url(
ClientMethod="put_object",
Params={"Bucket": "user-uploads", "Key": "avatars/123.png"},
ExpiresIn=900, # 15 minutes
)
# The client uploads straight to S3 with an HTTP PUT to `url` — no AWS creds needed.
Exam decision pattern: whenever a scenario needs temporary, direct, credential-free access to a single object — user avatar uploads, time-limited report downloads, sharing a private object — reach for a presigned URL. If the requirement is broader (serve a whole private site, cache at the edge, geo-restrict), that’s CloudFront with an origin access control / signed URLs or cookies instead. Knowing which tool matches which requirement is exactly what the question is probing.
Idempotency and Safe Retries
There’s a hidden danger in retrying: if the first request actually succeeded but the response was lost, a naive retry can perform the action twice — charging a card twice, sending a message twice, inserting a duplicate record. Idempotency is the property that performing an operation multiple times has the same effect as performing it once. The exam expects you to recognise where AWS gives you idempotency tools:
- SQS FIFO queues use a
MessageDeduplicationIdto discard duplicate sends within a 5-minute window. - DynamoDB conditional writes (
ConditionExpression, e.g.attribute_not_exists(pk)) let you make an insert safe to retry — the second attempt fails harmlessly instead of duplicating. - Many mutating APIs accept a client token (
ClientRequestToken, e.g. in Step FunctionsStartExecutionor various run/create calls) so AWS itself deduplicates repeated calls.
The takeaway for retries: retry logic and idempotency are two halves of the same design. You retry to survive transient failures; you make operations idempotent so those retries don’t cause damage. A scenario mentioning “duplicate records after a network timeout” is pointing you at idempotency, not at turning off retries.
Putting It Together: A Question-Reading Framework
When a DVA-C02 question describes application-to-AWS interaction, classify it fast:
| Scenario signal | Category | Exam-correct move |
|---|---|---|
Works locally, AccessDenied on EC2/ECS | Credentials | Attach an IAM role; stop shipping keys |
Bursts of ThrottlingException / 429 / 503 | Retries | Exponential backoff with jitter (SDK standard/adaptive mode) |
DynamoDB ProvisionedThroughputExceeded | Retries + capacity | Backoff and raise throughput / go on-demand |
| ”Results are incomplete for large datasets” | Pagination | Follow the continuation token / use a paginator |
| Let users upload/download a private object directly | Presigned URL | Backend signs a time-limited URL |
| Duplicate side effects after a timeout | Idempotency | Dedup ID / conditional write / client token |
That table is most of the SDK-mechanics surface area of the Development domain. Notice how none of it is about a specific service’s feature list — it’s about behaviour. For the full domain breakdown and where these fit, keep the DVA-C02 exam topics guide beside you, and slot this material into a paced Developer Associate study plan. When something fails in a running app, the observability side is covered in the monitoring and troubleshooting guide, and how it all gets deployed lives in the CI/CD guide.
From Recognising Patterns to Answering Fast
The reason these mechanics reward practice is that the exam rarely asks them directly — it embeds them in scenarios. You won’t see “what is exponential backoff?”; you’ll see a paragraph about intermittent ThrottlingExceptions under load and four plausible-sounding fixes, only one of which is backoff. Speed comes from having seen the pattern enough times that the signal jumps out at you.
That’s the gap targeted practice closes. Start with the free Developer Associate resources and the practice questions to expose yourself to the scenario framing. When you want realistic, exam-weighted reps with an explanation for every option, the Sailor.sh AWS Developer Associate (DVA-C02) Mock Exam Bundle runs eight full mock exams with detailed answer rationales — including the SDK, credentials, retry, and S3 access patterns covered here — so you learn why the throttling answer is backoff and not a bigger instance, not just that it is. Pair that with the broader DVA-C02 exam guide for 2026 and you’ll walk in recognising these questions on sight.
Frequently Asked Questions
How does the AWS SDK find credentials?
It walks the default credential provider chain in order: environment variables, shared config/credentials files and profiles, web identity/SSO, container/IRSA credentials, and finally the EC2 instance metadata service (the attached IAM role). It uses the first source that returns credentials. On AWS compute you should rely on an attached IAM role rather than hardcoded keys.
What is exponential backoff with jitter, and when do I use it?
Exponential backoff means waiting progressively longer between retries (1s, 2s, 4s…) up to a cap; jitter adds randomness so many clients don’t retry in lockstep. Use it whenever a call is throttled — ThrottlingException, ProvisionedThroughputExceeded, HTTP 429/503. The AWS SDKs implement this in their standard and adaptive retry modes.
Why am I only getting some of my S3 objects or DynamoDB items back?
AWS APIs paginate: ListObjectsV2 caps at 1,000 keys, DynamoDB Scan/Query cap at 1 MB per response. If the response is truncated it returns a continuation token (NextContinuationToken, NextToken, or LastEvaluatedKey). Keep requesting with that token until none is returned, or use the SDK’s paginator to handle it automatically.
When should I use a presigned URL?
Use a presigned URL when a client needs temporary, direct access to a specific S3 object without its own AWS credentials — for example, letting users upload or download files straight to/from S3 without routing the bytes through your application. The URL is scoped to the operation, object, and expiry you sign it with, and it’s bounded by the signer’s permissions.
What’s the difference between a presigned URL and CloudFront signed URLs?
A presigned S3 URL grants temporary access to one object directly from S3, ideal for uploads/downloads. CloudFront signed URLs (or cookies) control access to content served through the CloudFront CDN, adding edge caching, geo-restriction, and broader content protection. Choose presigned URLs for single-object, direct-to-S3 access; choose CloudFront for delivering protected content at scale through the edge.
How do I make retries safe against duplicates?
Make the operation idempotent. Use SQS FIFO MessageDeduplicationId, DynamoDB conditional writes (attribute_not_exists), or a ClientRequestToken on APIs that support it. Then a retried request that actually succeeded the first time won’t cause a second side effect.