Chapter 1
Development with AWS Services
Domain 1 is the largest part of the DVA-C03 exam at 30% of the scored content, and it is the most hands-on domain. The questions assume you have written, configured, and debugged real applications: Lambda functions, API Gateway endpoints, DynamoDB tables, queues, event buses, containers, and code that calls AWS services through the SDKs. This chapter builds that working knowledge service by service, with the limits, defaults, and trade-offs the exam likes to test. Read it with one habit in mind: for every feature, ask "what is the default, what is the limit, and when would I choose the alternative?" That is exactly how the exam asks.
Two themes are new in DVA-C03 and run through this chapter. First, AI-assisted development - Amazon Q
Developer and Kiro - is part of the developer's normal toolkit, and you are expected to know where it fits in the workflow. Second, applications now call managed AI services such as Amazon Bedrock from ordinary application code, and that integration is tested at a developer level: API calls, streaming, permissions, and error handling - not model science.
1.1 Lambda Development and Configuration
AWS Lambda is the default compute answer in this domain. The exam tests how a function is structured, how it is configured, and how it behaves under load - not just what Lambda is.
The handler and the runtime
Every function has a handler: the method Lambda invokes when an event arrives. The handler receives two inputs - the event (a JSON document whose shape depends on the trigger) and the context object (request ID, function name, remaining time via get_remaining_time_in_millis(), memory limit, and the CloudWatch log group). A well-structured function keeps the handler thin: parse the event, delegate to business logic, return a response. Heavy initialization - SDK clients, database connections, downloaded reference data - belongs outside the handler so it runs once per execution environment and is reused across warm invocations.
Know the invocation models cold, because many questions hinge on them:
| Invocation model | Synchronous | Asynchronous |
|---|---|---|
| Poll-based (event source mapping) | How it works | Caller waits for the response; errors return to the caller |
| Lambda queues the event and returns immediately; Lambda retries failures twice by default | Lambda polls the source and invokes the function with a batch | Typical sources |
| API Gateway, SDK calls, Step Functions | S3 events, SNS, EventBridge | SQS, Kinesis, DynamoDB Streams, Kafka |
For asynchronous invocations, Lambda destinations give you control over outcomes you cannot get from retries alone. You can configure an on-success and an on-failure destination per function (SQS, SNS,
EventBridge, or another Lambda function). After retries are exhausted, a failed event is sent to the on-failure destination instead of being dropped - the modern alternative to wiring a dead-letter queue at the function level, and destinations also capture successful results. For poll-based sources, the equivalent tools are the source's own redrive/DLQ settings plus, for stream sources, partial-batch failure reporting (covered below).
Environment variables
Environment variables are the standard way to pass configuration - table names, bucket names, feature flags, log levels - without redeploying code. Key facts:
- The total size of all environment variables is limited to 4 KB.
- Variables are encrypted at rest by default using an AWS managed KMS key; you can supply a customer
managed key for tighter control or audit requirements.
- Values are available to code as ordinary OS environment variables, so changing one creates a new version
of the function's configuration - code must tolerate the value it reads at cold start.
- Secrets do not belong in plain environment variables for anything sensitive. Store them in Secrets Manager
or Parameter Store and retrieve them at runtime (the Lambda Parameters and Secrets extension caches them in the execution environment, reducing API calls and latency).
Layers and dependencies
A layer is a ZIP archive of libraries, a custom runtime, or shared code that you attach to a function so the deployment package stays small and dependencies are managed once. Facts the exam expects:
- A function can use up to 5 layers, merged into
/optin the order you specify. - Combined size of the function package plus layers counts against the unzipped deployment limit.
- Layers are versioned; updating a layer publishes a new version and functions keep using the version they
reference until you update them.
- Container images are the alternative packaging model: images up to 10 GB (versus 250 MB unzipped for
ZIP deployments), built from a base image, stored in Amazon ECR, and useful when dependencies are large or a consistent build environment matters.
Memory, CPU, and timeout
Lambda's most-tested configuration relationship: you choose memory; CPU scales with it. Network bandwidth and disk I/O scale proportionally as well. The key numbers:
| Setting | Memory |
|---|---|
| CPU | Timeout |
| /tmp storage | Range / limit |
| 128 MB to 10,240 MB, in 1 MB increments | Proportional to memory; roughly 1 vCPU at 1,769 MB, up to 6 vCPUs at 10,240 MB |
| 1 second to 15 minutes (900 seconds) maximum | 512 MB by default, configurable up to 10,240 MB |
| Setting | Range / limit | |
|---|---|---|
| ZIP deployment package | 50 MB direct upload (zipped), 250 MB unzipped including layers | |
| Container image | Up to 10 GB | |
| Environment variables | 4 KB total |
Because CPU is tied to memory, a CPU-bound function can get faster and cheaper at a higher memory setting:
doubling memory may more than halve duration, and you pay per GB-second, so the total cost can drop. The inverse trap also appears on the exam: raising memory does nothing for a function whose time is spent waiting on a downstream HTTP call. Match the tool to the bottleneck.
If a question says a function times out at exactly the same wall-clock point regardless of memory, the bottleneck is downstream waiting or the configured timeout itself - not CPU. Memory questions are about
CPU-bound work.
Concurrency basics
Concurrency is the number of simultaneous executions of your function. The essentials:
- Unreserved concurrency is the shared account/Region pool (default soft limit of 1,000 concurrent
executions per Region, which can be raised by request). One runaway function can consume the pool and starve others.
- Reserved concurrency guarantees a set number of executions for one function and caps it at that number
- use it to protect a critical function and to throttle a noisy one. Setting reserved concurrency to 0 stops the function entirely, a useful emergency brake.
- Provisioned concurrency pre-initializes execution environments so invocations do not pay cold-start cost.
It is configured on a version or alias and pairs with auto scaling; the optimization details belong to Domain
4, but know what it is and that it costs money while provisioned.
- When requests exceed available concurrency, synchronous callers receive a throttling error (HTTP 429);
asynchronous events are retried and eventually sent to the on-failure destination or dropped.
Common traps - Lambda
- Putting SDK client creation and large downloads inside the handler, then wondering why every invocation
is slow.
- Assuming reserved concurrency only guarantees capacity - it also caps the function.
- Expecting environment variables to hold secrets or large payloads (4 KB ceiling).
- Forgetting that
/tmpcontents persist only for the life of the execution environment; it is scratch space, not
storage.
Execution environment. The isolated runtime container Lambda creates to run your function, holding the runtime, your code, and any layers. Lambda may freeze it between invocations and reuse it (a "warm start"), which is why initialization done outside the handler is reused and files in /tmp can survive between invocations - and why you must never treat it as permanent storage or assume it is fresh.
Provisioned concurrency. A setting that pre-initializes a fixed number of execution environments for a specific function version or alias, so those invocations skip cold-start initialization. You pay for the provisioned capacity whether it is used or not, which makes it a latency tool for predictable, latency-sensitive traffic rather than a general performance setting.
In Lambda, memory and CPU are not independent dials: the memory you choose automatically sets the CPU, network bandwidth, and I/O the function receives. Students often treat memory as purely a capacity or cost setting and miss that raising it can make CPU-bound code finish so much faster that the total bill falls - while doing nothing for a function whose time is spent waiting on a downstream service.
1.2 API Gateway
API Gateway is how most exam applications expose Lambda and other backends over HTTP. You need the
REST/HTTP distinction, integration types, authorization options, and how deployments reach a stage.
REST APIs vs HTTP APIs
| Positioning | Authorizers | |
|---|---|---|
| REST API | Full-featured, original offering | IAM, Lambda authorizers, Cognito user pools |
| HTTP API | Simpler, lower latency, lower cost for common cases | JWT authorizers (OIDC/JWT), Lambda authorizers |
| API keys and usage plans | ||
|---|---|---|
| Request validation | Other features | WebSocket APIs |
| REST API | Supported | |
| Built-in model/parameter validation | WAF integration, caching, mutual TLS, resource policies, private APIs | Separate API type for two-way connections |
| HTTP API | Not supported | |
| Not supported | Automatic deployments option, simpler CORS configuration | - |
The deciding-question pattern is consistent: if the stem mentions API keys, usage plans, request validation, or per-client throttling quotas, the answer is a REST API. If it asks for the cheapest, lowest-latency way to front
Lambda or an HTTP backend with JWT authorization, it is an HTTP API.
Integrations
An integration connects a method or route to a backend. Know the types and the proxy distinction:
- Lambda proxy integration (AWS_PROXY): the entire request - headers, body, query string, path
parameters, authorizer context - is passed to the function as a single event, and the function's return value
(status code, headers, body) becomes the response. This is the default exam choice because the code controls the response.
- Lambda custom (non-proxy) integration: you write mapping templates (Velocity Template Language) to
transform request and response. Used when legacy functions cannot change; a favorite distractor.
- HTTP integration proxies to an HTTP backend; AWS service integration calls an AWS API directly (for
example, API Gateway -> SQS or DynamoDB without a Lambda in between); mock integration returns a response without any backend, useful for CORS preflight and stubs; VPC link (private integration) reaches resources inside a VPC, such as an internal ALB.
Exam tip: "Remove the Lambda function and have API Gateway write directly to the queue" is a real pattern - the AWS service integration to SQS appears often as the lowest-overhead answer.
Authorization at a developer level
- IAM authorization: callers sign requests with SigV4; fine-grained and native to AWS callers.
- Lambda authorizer: a function that inspects a token (TOKEN type) or request parameters (REQUEST type)
and returns an IAM policy. Results are cached by token for a configurable TTL, which is why a revoked token can keep working briefly - a tested trap.
- Cognito user pool authorizer (REST APIs): validates JWTs issued by a user pool natively.
- JWT authorizer (HTTP APIs): API Gateway validates the token against the issuer's keys; no custom code.
- Resource policies control which sources (accounts, IP ranges, VPC endpoints) may call the API - required
for private APIs.
Stages and deployments
A stage is a named deployment environment (dev, test, prod) with its own settings: throttling, caching, logging, and stage variables - name/value pairs passed to integrations, the classic way to point the prod stage at a different Lambda alias or backend than the test stage from one API definition. In REST APIs, changes take effect only after you deploy the API to a stage; HTTP APIs can deploy automatically. Stage-level caching (with a per-method override and cache TTL), canary deployments on a stage, and method-level throttling overrides are all fair game for questions.
Common traps - API Gateway
- Choosing a custom integration and mapping templates when the stem never asks for transformation -
proxy is the simpler default.
- Forgetting that a Lambda authorizer's cached policy can delay revocation.
- Editing a REST API and assuming the change is live without redeploying to the stage.
- Reaching for Lambda where a direct AWS service integration removes a component the question wants
gone.
Lambda proxy integration. An API Gateway integration type (AWS_PROXY) that passes the complete incoming request - method, headers, body, query string, path parameters, and authorizer context - to a
Lambda function as a single event, and uses the function's returned status code, headers, and body directly as the HTTP response. Because the code shapes the response, it needs no mapping templates and is the default integration pattern for Lambda-backed APIs.
Remember the timeout distinction that tripped up older material. API Gateway REST APIs have a default integration timeout of 29 seconds. That limit can now be raised for Regional and private REST APIs through
Service Quotas - but not for edge-optimized REST APIs, and HTTP APIs have a fixed timeout of 30 seconds. What you should carry into the exam is the default value, and the instinct the exam encourages: long-running work belongs behind an asynchronous boundary (queue it, store it, notify later), not in a synchronous request.
1. A product team wants per-client quotas and server-side request validation on its public API. A colleague proposes an HTTP API because it is cheaper. Will that work?
2. You edited a method on a REST API and saved it, but clients still see the old behavior. What step did you miss?
Answers: 1. No - API keys, usage plans with quotas, and built-in request validation are REST API features that
HTTP APIs do not offer. 2. Deploying the API to the stage again; REST API changes do not take effect until they are deployed.
1.3 DynamoDB
In DVA-C03 the DynamoDB skills are consolidated into a broader single area, which means the exam tests the service from many angles rather than as a checklist of narrow facts. The core model, read patterns, indexes, and change features below are the angles that matter.
Keys and the data model
A table has a partition key (hash) and optionally a sort key (range); together they form the primary key and must be unique per item. DynamoDB hashes the partition key to decide which physical partition stores the item, which is why key design is the single biggest performance decision: a partition key with many distinct, evenly accessed values spreads load; a low-cardinality or skewed key (for example, today's date, or one celebrity user) concentrates traffic on one partition and causes throttling even when the table has spare capacity - the famous hot partition problem.
Items in the same partition, sharing a partition key, are stored together ordered by sort key - which is what makes one-to-many modeling (CUSTOMER#123 with sort keys like PROFILE, ORDER#2026-10-01,
ORDER#2026-10-14) so effective: one Query retrieves the whole item collection.Query vs Scan
| Key requirement | Efficiency | |
|---|---|---|
| Filter expressions | Typical use | Query |
| Partition key equality condition is mandatory; sort key condition optional | Reads only items in the matching partition | Applied after items are read (do not reduce consumed capacity) |
| Production access patterns | Scan | None - reads every item in the table or index |
| Reads everything, then applies any filter | Same | One-off exports, analytics, admin jobs |
| Query | Scan | |||
|---|---|---|---|---|
| Capacity | Only for items examined by the query | For every item in the table, whether returned | ||
| consumed | or not |
The trap repeats across exams: a filter expression does not reduce the read capacity a Scan or Query consumes, because filtering happens after the read. If a question asks how to read less data, the fix is a key condition, a projection, or a better key design - never a filter.
Capacity in brief
| Term | 1 RCU |
|---|---|
| 1 WCU | Provisioned mode |
| On-demand mode | Strongly consistent read |
| Eventually consistent read | Meaning |
| One strongly consistent read of up to 4 KB per second, or two eventually consistent reads of up to 4 KB | One write of up to 1 KB per second |
| You set capacity; auto scaling can adjust it; throttling occurs when exceeded | Pay per request; scales automatically; best for unpredictable or spiky workloads |
| Returns the result of all successful writes before it; costs more; not supported on GSIs | May lag recent writes slightly; the default; half the RCU cost |
Indexes: GSI and LSI
Indexes let you query by attributes other than the primary key. The choice between them is a standard exam decision:
| Key structure | Creation | |
|---|---|---|
| Consis- tency | Capacity | Scope |
| Limits | Global secondary index (GSI) | Its own partition key and sort key, different from the table's |
| Any time | Eventually consistent reads only | Has its own provisioned capacity (or on-demand billing) |
| The "global" refers to spanning all partitions | Default quota of 20 per table | Local secondary index (LSI) |
| Same partition key as the table, different sort key | Only when the table is created | Strongly or eventually consistent reads |
| Shares the table's capacity | Items share the table partition key; item collections limited to 10 GB | Maximum 5 per table |
| Global secondary index (GSI) | Local secondary index (LSI) | |||
|---|---|---|---|---|
| Projec- | KEYS_ONLY, INCLUDE, or ALL | Same options | ||
| tion |
Rules of thumb the exam rewards: need to query by an attribute that is not the table's partition key -> GSI. Need a different sort order on the same partition key, with strong consistency -> LSI (and if the table already exists, you cannot add one - another tested trap). An under-provisioned GSI can throttle writes to the whole table, because a write that cannot be replicated into the index is rejected.
Streams, TTL, and transactions
- DynamoDB Streams capture item-level changes (inserts, updates, deletes) in near real time, retained for
24 hours. Stream view types control what each record contains: KEYS_ONLY, NEW_IMAGE, OLD_IMAGE, or
NEW_AND_OLD_IMAGES. The classic pattern is a Lambda event source mapping processing the stream - forexample, updating a search index or aggregating data - and stream consumers must be written idempotently because delivery is at least once.
- TTL (time to live): designate a numeric epoch-seconds attribute; DynamoDB deletes expired items
automatically at no extra cost. Deletion is background work and typically completes within a few days of expiry - not instantly - so code must still check the expiry attribute itself when correctness depends on it.
Expired-but-not-yet-deleted items still appear in reads unless you filter them out.
- Transactions:
TransactWriteItemsandTransactGetItemsprovide ACID semantics across up to 100
items (4 MB total) in one or more tables - the answer when a scenario demands all-or-nothing updates across items, or when you must prevent double-processing with condition checks evaluated atomically.
Transactions consume double the standard capacity. For single items, a conditional write (
ConditionExpression) is the lighter tool: the write succeeds only if the condition holds, and a failedcondition raises ConditionalCheckFailedException.
DAX
DynamoDB Accelerator (DAX) is a managed, in-memory cache that sits in front of DynamoDB and speaks the
DynamoDB API, so most applications adopt it by changing the client endpoint rather than rewriting data code.
Know: read latency drops to microseconds; DAX maintains an item cache (point reads/writes) and a query cache; writes are write-through to DynamoDB; strongly consistent reads are passed through to DynamoDB rather than served from cache; negative caching remembers "item not found" results briefly. DAX helps read-heavy workloads with repeated access to the same items - it does nothing for write bottlenecks or hot partitions on writes.
Common traps - DynamoDB
- Using Scan with a filter expression as the "efficient" answer.
- Choosing a GSI when the scenario requires strongly consistent reads.
- Trying to add an LSI to an existing table.
- Treating TTL as real-time deletion.
- Forgetting that a throttled GSI back-pressures writes to the base table.
Partition key. The attribute DynamoDB hashes to decide which physical partition stores an item; when a sort key is also defined, the two together form the primary key. Because every Query must begin with a partition key value, and a low-cardinality or skewed partition key overloads a single partition, choosing a high-cardinality, evenly accessed partition key is the most important DynamoDB design decision a developer makes.
Filter expressions are applied after items are read, not before. A Query or Scan with a filter expression consumes capacity for every item it examines, including the ones the filter discards - so a filter can never make a read cheaper. To read less data, change the key condition, trim the projection, or fix the key design itself.
1.4 S3 and Other Data Stores for Developers
S3 essentials
Amazon S3 is the exam's default object store, and developer questions concentrate on how code interacts with it:
- Consistency: S3 provides strong read-after-write consistency for PUTs, DELETEs, and LIST operations - a
new object is immediately readable. Outdated advice about eventual consistency for new objects is exactly that: outdated.
- Presigned URLs: generate a URL that grants time-limited access to a specific object (GET or PUT) using
your credentials' permissions. This is the standard answer when users should upload or download directly without routing bytes through your servers, and its expiry is part of the security design.
- Multipart upload: recommended for objects over 100 MB and required beyond 5 GB in a single PUT. Parts
are 5 MB to 5 GB (except the last), up to 10,000 parts, uploaded in parallel and assembled by
CompleteMultipartUpload; remember to abort incomplete uploads - orphaned parts still incur storage charges, and a lifecycle rule can clean them up automatically.
- Versioning protects against accidental overwrite and delete, and pairs with MFA Delete for sensitive
buckets. A suspended versioning state is not the same as never-enabled.
- Event notifications can invoke Lambda, SQS, or SNS directly, and EventBridge offers richer filtering; this is
the trigger behind most "process the file as soon as it lands" scenarios.
- Storage classes matter to developers mainly through lifecycle transitions and retrieval behavior (for
example, archive classes are not millisecond-retrieval); the deep cost/architecture analysis belongs to other exams.
Size landmarks: a single PUT can carry up to 5 GB; a single object can be up to 5 TB via multipart. Bucket names are globally unique.
The other stores at a glance
- Amazon RDS / Aurora: relational data with SQL, joins, and transactions. Developer facts: use RDS Proxy
when many short-lived connections (classically from Lambda) would overwhelm the database - it pools and reuses connections. Parameter groups and automated backups are operational, but connection management is the developer-level issue.
- Amazon ElastiCache: managed Redis or Memcached for caching and session data - covered with caching
patterns in §1.8.
- Amazon EFS: shared file system mounted by Lambda (via VPC) and containers when code needs a real file
system interface or shared state across many concurrent executions, up to Lambda's /mnt mount points.
- Parameter Store and Secrets Manager as data stores for configuration: Parameter Store for config values
and simple secrets (Standard tier is free, with size and throughput limits), Secrets Manager for credentials needing automatic rotation. This distinction recurs in Domain 2.
Presigned URL. A URL generated locally by the SDK that grants time-limited access to one specific S3 object, signed with the generator's credentials, for either a download (GET) or an upload (PUT). Anyone holding the
URL can use it until it expires, which lets clients transfer bytes directly with S3 instead of routing them through your servers - and the expiry window is part of the security design.
1. A mobile app must upload 800 MB video files to S3, and restarting a failed upload from byte zero is unacceptable. What upload approach should it use?
2. An old design document warns that reading a brand-new object immediately after its PUT may return "not found." Is that still expected behavior on S3 today?
Answers: 1. Multipart upload - parts upload in parallel and only failed parts need to be retried; it is recommended above 100 MB, and a single PUT cannot exceed 5 GB. 2. No - S3 provides strong read-after-write consistency for new objects, so the read should succeed immediately.
1.5 Messaging and Streaming
Decoupling is the architectural heartbeat of this exam. Six services recur, and questions are won by matching the scenario's delivery semantics to the right one.
Amazon SQS
SQS is the workhorse queue: producers send messages, consumers poll, process, and delete them.
| Property | Ordering | Delivery |
|---|---|---|
| Through- put | Dedupli- cation | Use when |
| Standard queue | Best-effort | At least once (duplicates possible) |
| Nearly unlimited | None | Order does not matter, consumers are idempotent |
| FIFO queue | Guaranteed, per message group | Exactly-once processing via deduplication |
| 300 TPS without batching; up to 3,000 TPS with batching (default mode; high-throughput mode is far higher) | 5-minute deduplication window, via deduplication ID or content-based | Order or exactly-once matters |
Core mechanics the exam tests relentlessly:
- Visibility timeout (default 30 seconds, maximum 12 hours): while a consumer processes a message, it is
invisible to others. If processing outlives the timeout, the message reappears and gets processed twice.
The fix is a longer timeout, or ChangeMessageVisibility heartbeats during processing - and the diagnosis for "messages are being processed twice" is almost always this setting.
- Retention: messages can be kept 60 seconds to 14 days (default 4 days).
- Long polling (
WaitTimeSecondsup to 20) reduces empty receives and cost versus short polling - the
default recommendation.
- Dead-letter queues and redrive policy: after
maxReceiveCountfailed receives, the message moves to a
DLQ instead of looping forever - the "poison message" pattern. A DLQ alarm plus inspection beats silent loss.
- Delay queues/delayed messages: delivery can be delayed up to 15 minutes.
Amazon SNS
SNS is managed pub/sub: publishers send to a topic, and every subscribed endpoint (SQS queues, Lambda,
HTTPS, email, SMS, mobile push) receives a copy. Key developer facts: fan-out is the signature pattern - SNS -> multiple SQS queues decouples one event to many independent consumers, each with its own queue, retries, and DLQ. Filter policies on subscriptions let each subscriber receive only matching messages, so filtering logic
Message size: up to 1 MiB (raised from 256 KiB in August 2025); even larger payloads go in S3 with a pointer in the message (the "extended client" pattern).
Amazon EventBridge
EventBridge is a serverless event bus built for routing application events with rules. Events (JSON with a defined structure) land on an event bus - the default bus receives AWS service events; custom buses carry your application's events; partner buses carry SaaS events. Rules match events by pattern (source, detail-type, and any field of the JSON body, including nested matching and prefix/exists operators) and route to targets: Lambda,
SQS, SNS, Step Functions, API Gateway, and more, with input transformation available. Also know: the schema registry and schema discovery, archives and replay (store events and replay them through rules - the key differentiator when a stem says "reprocess past events"), and EventBridge Scheduler for cron/one-time scheduled invocations at scale. Pipes add point-to-point connections with filtering and enrichment between sources and targets.
Step Functions
Step Functions orchestrate multi-step workflows as state machines written in Amazon States Language. State types to recognize: Task (do work - usually Lambda or a direct service integration), Choice (branching), Parallel
(concurrent branches), Map (run the same steps over each element of an array - the distributed Map mode scales to large datasets in S3), Wait, Pass, Succeed, and Fail. Error handling is declarative: Retry (with backoff) and Catch on states. The workload split: Standard workflows run up to one year, guarantee exactly-once state execution, and suit long-running, auditable processes; Express workflows run up to five minutes at high volume and low cost for streaming/high-throughput jobs. Direct ("optimized") service integrations let a state machine call services like DynamoDB or SQS without a Lambda middleman.
Kinesis Data Streams and Amazon Data Firehose
These two are confused constantly, and the exam exploits it.
| Purpose | Consum- ers | |
|---|---|---|
| Destina- tions | Scaling | Kinesis Data Streams |
| Real-time stream processing; you build consumers | Your code (KCL/Kinesis Agent/SDK), Lambda, multiple applications read independently | n/a (consumers pull) |
| Shards you manage (provisioned mode) or on-demand mode | Amazon Data Firehose | Delivery service: load streaming data into destinations |
| None you manage - Firehose writes to the destination | S3, Redshift, OpenSearch, Splunk, HTTP endpoints, and others | Fully serverless, automatic |
leaves your code. FIFO topics can deliver to standard SQS queues (since 2023), but ordering and deduplication hold only with FIFO queues. Messages up to 256 KB by default, raisable to 1 MiB via MaximumMessageSize.
| Delivery timing | ||
|---|---|---|
| Replay | Transfor- mation | |
| Kinesis Data Streams | Real-time, records available in milliseconds; retention 24 hours by default, extendable to 365 days | Yes - consumers re-read within the retention window |
| In your consumers | Amazon Data Firehose | |
| Near real-time: buffered by size or time (as low as 60-second intervals) | No replay | Optional Lambda transformation and format conversion (e.g., to Parquet) |
Capacity landmarks for Data Streams: one shard ingests up to 1 MB/second or 1,000 records/second, and serves up to 2 MB/second of reads shared across consumers (enhanced fan-out gives each registered consumer its own 2 MB/second). Sequence numbers order records within a shard - so the partition key choice decides ordering, exactly as in DynamoDB.
Choosing among them
| Scenario cue | Buffer work, smooth spikes, decouple two components |
|---|---|
| One event, many independent consumers, each with own processing | Route events by content, integrate AWS/SaaS events, replay events |
| Multi-step process with branching, retries, human-scale durations | High-volume clickstream/telemetry needing custom consumers and replay |
| Load streaming data into S3/OpenSearch with minimal code | Answer |
| SQS | SNS fan-out to SQS queues |
| EventBridge | Step Functions |
| Kinesis Data Streams | Amazon Data Firehose |
Common traps - messaging and streaming
- Assuming SQS delivers exactly once on standard queues - consumers must be idempotent.
- Choosing Kinesis when the requirement is simply "get the data into S3" - that is Firehose's whole job.
- Forgetting the visibility timeout when a duplicate-processing symptom appears.
FIFO end-to-end: an SNS FIFO topic CAN deliver to a standard SQS queue (since September 2023), but ordering and deduplication are then lost; and ordering in FIFO queues is per message group, not global.
FIFO queue. An SQS queue type that preserves message order within a message group and provides exactly-once processing through a 5-minute deduplication window, using a message deduplication ID or content-based deduplication. The trade-off is throughput - far lower than a standard queue's near-unlimited rate - so FIFO is chosen when ordering or exactly-once semantics are required, not as a default.
Ordering in these services is scoped, not global: SQS FIFO guarantees order only within a message group ID, and Kinesis Data Streams guarantees it only within a shard. Both scale by spreading work across more groups or shards selected by well-chosen keys, so "strictly ordered everything, in one sequence" is neither what they offer nor what most scenarios actually need.
1.6 Containers for Developers
DVA-C03 adds explicit container coverage. You are tested as a developer who builds images and runs them on
AWS - not as a Kubernetes administrator.
Amazon ECR
Elastic Container Registry stores your Docker/OCI images. Developer essentials: repositories can be private or public (ECR Public); images are pushed and pulled with standard Docker commands after an authentication token from get-login-password (tokens last 12 hours); image scanning (basic scan-on-push, or enhanced scanning with Amazon Inspector) finds OS and library vulnerabilities; lifecycle policies automatically expire old or untagged images to control storage cost; cross-Region and cross-account replication keeps images close to where they run. Lambda container images, ECS tasks, and EKS pods all pull from ECR.
ECS and Fargate
Elastic Container Service runs containers described by a task definition: a JSON template naming the image,
Exam tip. FIFO guarantees hold only end to end: a FIFO topic can subscribe a standard SQS queue (allowed since
September 2023), but ordering and deduplication are lost there. If a scenario needs strict ordering preserved, the subscriber must be a FIFO queue.
CPU and memory, port mappings, environment variables, logging configuration, and IAM roles. Two role names are a guaranteed exam item:
- Task execution role - used by the ECS agent/container runtime itself: pulling the image from ECR, fetching
secrets, writing logs.
- Task role - used by your application code inside the container to call AWS APIs. Least privilege belongs
here.
A service keeps a desired count of tasks running, integrates with load balancers, and performs rolling deployments. Launch types: the EC2 launch type runs tasks on instances you manage; AWS Fargate is the serverless launch type - no instances to patch or scale, you specify task-level CPU and memory (valid combinations, from 0.25 vCPU/0.5 GB up to 16 vCPU/120 GB) and pay for what the task reserves. Fargate removes infrastructure decisions; EC2 launch type remains the answer when a scenario needs GPUs, specific instance types, or daemon-level control. ECS Exec lets you open a shell in a running container for debugging.
Amazon EKS
Elastic Kubernetes Service provides a managed Kubernetes control plane; you deploy with standard Kubernetes manifests and tooling. For this exam, know the positioning rather than the internals: choose EKS when the organization is standardized on Kubernetes or needs portability; choose ECS for the simpler, AWS-native path.
IRSA (IAM Roles for Service Accounts) gives pods their own IAM roles - the EKS counterpart of the ECS task role - and EKS can run pods on Fargate profiles as well as managed node groups.
Common traps - containers
- Swapping the task role and task execution role.
- Assuming Fargate tasks can use any CPU/memory pairing - only defined combinations are valid.
- Placing a persistent local disk expectation on Fargate tasks; storage is ephemeral unless you attach EFS.
1. An ECS task on Fargate fails at startup with an image-pull error from ECR, before any application code runs.
Which IAM role do you check first - and why not the task role?
2. A team standardized on Kubernetes wants to lift its existing manifests to AWS with the least rework. Should it choose ECS or EKS?
Answers: 1. The task execution role - the ECS runtime uses it to pull the image, fetch secrets, and write logs;
the task role only grants permissions to code already running inside the container. 2. EKS - it runs standard
Kubernetes manifests, while ECS uses its own task definition model and would force a rewrite of the deployment definitions.
Exam tip. Whenever a question describes container permissions, first ask who is acting: the platform starting the task (task execution role, or IRSA for EKS pods) versus the application code inside it (task role). Most container IAM traps are simply those two roles swapped.
1.7 AI-Assisted Development and Calling Bedrock from Code
Amazon Q Developer
Amazon Q Developer is AWS's AI assistant for the development lifecycle. At a developer level, know where it appears and what its agents do:
- In the IDE (VS Code, JetBrains, and others) and on the command line: chat about code, inline code
completions, explanations, and generated unit tests.
- Agents for tasks:
/devimplements a feature from a description across your codebase;/transform
performs large-scale upgrades and migrations (the well-known case is Java version upgrades, plus .NET and mainframe modernization paths); /review runs a code review for security and quality issues; agents also generate documentation.
- In the AWS Management Console and AWS APIs: Q Developer answers questions about your resources,
helps diagnose errors (for example, EC2 or Lambda console errors), and assists in services such as
CodeCatalyst successors and the AWS documentation/CLI environment.
- Q Developer also supports customization on your private code repositories for Pro tier users, so
suggestions reflect internal libraries.
The exam angle is practical: which tool do you reach for to modernize a legacy codebase, generate tests, review a pull request, or explain an unfamiliar error? Q Developer (and Kiro, below) are the answers - AI assistance is treated as part of normal development, testing, and troubleshooting, which is why it appears in Domains 1, 3, and 4 alike.
Kiro
Kiro is AWS's agentic IDE, built around spec-driven development. Instead of prompting for code and hoping, you work from structured specifications: a requirements document (user stories with acceptance criteria in
EARS-style notation), a design document (architecture, components, data models), and a tasks list that the agent executes step by step. Three mechanisms distinguish it on the exam:
- Specs keep the agent anchored to approved requirements and design as it generates code across a
feature.
- Steering files give the project persistent context - conventions, libraries, and patterns the agent must
follow in every interaction.
- Agent hooks are event-driven automations that fire on actions such as saving a file or committing - for
example, updating tests or documentation automatically.
Kiro also supports vibe-style exploratory coding and MCP (Model Context Protocol) connections to external tools, but the tested identity is spec-driven: requirements -> design -> tasks -> code, with the developer reviewing each artifact.
Calling Amazon Bedrock from application code
Amazon Bedrock is the managed service for foundation models, but on this exam you meet it as an API your application calls. The developer-level surface:
- Permissions: your code's IAM role needs actions such as
bedrock:InvokeModel(orbedrock:Converse)
on the model resource; model access is enabled per account/Region.
- InvokeModel: the original API - you send a model-specific JSON request body (each model's native format)
to a model ID and parse its native response. Fine-grained, but the payload format differs per model family.
- Converse API: the newer, uniform interface - one request shape (messages, system prompt, inference
parameters) across models, with tool use and multimodal content expressed consistently. For new code,
Converse is the expected default, and exam questions treat it as the way to avoid per-model payload formats.
- Streaming:
InvokeModelWithResponseStreamandConverseStreamdeliver tokens incrementally - the
pattern for chat UIs that display answers as they are generated rather than waiting for completion.
- Guardrails at call time: a call can specify a guardrail identifier and version so content filtering and
denied-topic policies are evaluated on the request and response - as a developer you reference and attach guardrails; designing the wider AI governance framework around them is out of scope for this exam.
- Agents: Bedrock Agents let a model plan and execute multi-step tasks using your APIs (action groups
backed by Lambda). Bedrock AgentCore provides the managed runtime and surrounding services - runtime hosting, memory, identity, gateway, and observability - for running agents in production, including agents built with other frameworks.
- Operational behavior: Bedrock calls are ordinary HTTPS API calls from your function's perspective - they
can be throttled (handle ThrottlingException with backoff), they count against your latency budget, and prompt/response data in logs is a privacy concern, which connects directly to the AI security material in
Domain 2.
Out of scope here, and absent from this chapter by design: prompt engineering technique, retrieval-augmented generation design, model selection criteria, SageMaker AI, and AI governance design. You need to call and secure these services, not design the AI itself.
On this exam, calling Amazon Bedrock is an application-integration task, not an AI-design task. From your code's perspective, a Bedrock call is an ordinary HTTPS API call: it needs IAM permission (
bedrock:InvokeModel or bedrock:Converse) on the model, it can be throttled and therefore needs backoff,and its latency counts against your function's timeout budget. The Converse API exists so that this call has one consistent request shape across models instead of a different native payload format per model family.
1.8 SDK Patterns, Idempotency, and Caching
The last slice of Domain 1 is about how your code behaves as a client of AWS: retries, safe re-execution, and not calling services more than necessary.
Working with the AWS SDKs
- Retries with exponential backoff and jitter are built into the SDKs' standard retry mode - you rarely
hand-roll retry loops. Know why jitter matters (it prevents synchronized retry storms) and that non-idempotent client errors (validation failures, 4xx other than throttling) are not retried usefully.
- Paginators handle list APIs that return results a page at a time - forgetting pagination and silently seeing
only the first page is a classic bug the exam disguises as a data question.
- Waiters poll a resource until it reaches a desired state (for example, until a table is ACTIVE) instead of your
own sleep-loop.
- Presigned URLs and requests (§1.4) are generated locally by the SDK without an API call.
- Client-side timeouts and connection settings are your controls; a Lambda function calling a slow API
should set them deliberately rather than inherit defaults and burn its full 15 minutes.
- Prefer resource-level abstractions where the SDK offers them, but know the underlying API call - exam
stems describe API behavior, not library conveniences.
Idempotency
AWS delivery semantics are at-least-once in most places that matter (async Lambda retries, SQS standard queues, stream consumers), so handlers must be safe to run twice. Patterns the exam expects you to recognize and apply:
1. Idempotency key + conditional write: the client or event carries a unique token; the handler records it with a DynamoDB PutItem guarded by attribute_not_exists. If the condition check fails, the work was already done - return the original result instead of repeating it. Add a TTL so the idempotency table does not grow forever. (AWS Lambda Powertools' idempotency utility packages exactly this pattern.)
2. Natural idempotency by design: use PutItem/upserts keyed by the event's own identity instead of generating new IDs per attempt, so a retry overwrites rather than duplicates.
3. Deduplication built into services: SQS FIFO deduplication IDs, EventBridge event IDs for producer-side tracing, and transactional conditional writes in DynamoDB.
4. Partial batch responses for poll-based Lambda sources (SQS, Kinesis, DynamoDB Streams): return only the failed message/record IDs (ReportBatchItemFailures), so successful items in the batch are not retried and duplicated. Forgetting this is why "one bad record causes the whole batch to loop" - the question stem is a symptom of a missing partial-batch configuration.
Caching: DAX and ElastiCache
Caching appears in two flavors in this domain, and the exam wants you to place each correctly.
| What it caches | Latency effect | Adop- tion | |
|---|---|---|---|
| Data struc- tures | Persist- ence & HA | Scaling model | DAX |
| DynamoDB data, via the DynamoDB API | DynamoDB reads from milliseconds to microseconds | Change the client endpoint; minimal code change | DynamoDB items and query results |
| Managed cluster, replicas | Cluster nodes | ElastiCache for Redis | General-purpose: query results, sessions, leaderboards, computed data |
| Sub-millisecond reads from memory | Application code explicitly gets/sets cache entries | Rich: strings, hashes, sorted sets, pub/sub, streams | Replication, Multi-AZ automatic failover, snapshots |
| Sharding + replicas | ElastiCache for Memcached | Simple key-value objects | Same |
| Same | Strings/objects only | No replication or failover; nodes are independent | Add nodes (auto discovery) |
Caching strategies to name on sight: lazy loading (read-through on demand: check cache, on miss read the source and populate - risks stale data and a thundering herd on cold cache) and write-through (update the cache on every write - fresher data, extra write cost). Pair either with a TTL so staleness is bounded. ElastiCache is also the home of session state for web applications (replacing sticky sessions) and of rate-limit counters and leaderboards (Redis sorted sets).
Common traps - SDK, idempotency, caching
- Writing custom retry loops on top of the SDK's built-in retries.
- Assuming a message processed once means it ran once.
- Pointing DAX at a write-heavy or strongly-consistent-read workload and expecting improvement.
- Choosing Memcached when the scenario needs replication, failover, or anything beyond simple objects.
1. A Lambda function processing SQS batches keeps redelivering an entire batch of 50 messages because one malformed message always fails. What feature stops the 49 good messages from being reprocessed?
2. A read-heavy application repeatedly reads the same DynamoDB items and needs microsecond read latency with minimal code change. DAX or ElastiCache - and why?
Answers: 1. Partial batch responses - enable ReportBatchItemFailures on the event source mapping and return only the failed message IDs. 2. DAX - it speaks the DynamoDB API, so adoption is essentially an endpoint change; with ElastiCache the application must get and set cache entries explicitly.
End-of-Chapter Test
1. A Lambda function's execution time is dominated by CPU-heavy image processing. At 512 MB the function runs for 8 seconds and costs more than expected. Which change is most likely to reduce both duration and cost?
- Increase the function timeout to 900 seconds
- Increase the memory allocation, which proportionally increases CPU
- Add a second Lambda function to split the work
- Store the images in S3 instead of EFS
2. A team needs API keys, per-client usage plans with quotas, and server-side request validation for a public API backed by Lambda. Which API type should they choose?
- HTTP API
- WebSocket API
- REST API
- A private REST API with a resource policy
3. An application frequently queries orders by customerId, which is not the table's partition key. The table already exists. What is the correct way to make this query efficient, and what consistency limitation applies?
- Run a Scan with a filter expression; filters support strong consistency
- Add a local secondary index; it requires eventual consistency
- Add a global secondary index on customerId; it supports eventual consistency only
- Enable DAX; DAX makes non-key queries efficient
4. Orders from an SQS queue are processed correctly but each message is occasionally processed twice. The visibility timeout is set to 10 seconds while the average processing time is 45 seconds. What is the root cause and fix?
- The DLQ is missing; add one so duplicates are diverted
5. A pipeline must make incoming product events available to three independent teams, each processing them at its own pace with its own retry and failure handling. What is the best design?
- One SQS queue with three consumers competing for messages
- An SNS topic fanning out to three separate SQS queues, one per team
- A Kinesis data stream with three shards
- An EventBridge rule with three Lambda targets and no queues
6. A team must load streaming clickstream data into Amazon S3 in near real time, converting it to Parquet on the way in, with no servers or stream consumers to manage. Which service fits?
- Kinesis Data Streams with a Lambda consumer
- Amazon Data Firehose
- SQS with a scheduled Lambda poller
- EventBridge with an S3 target
7. A developer is adding a chatbot feature to an existing application. The code must call Amazon Bedrock with the same request format regardless of which model the team deploys, and display responses token by token as they arrive. Which API and method meet both requirements?
- InvokeModel, because it streams natively
- The Converse API with ConverseStream
- InvokeModelWithResponseStream with a different payload per model
- Bedrock Agents with synchronous invocation
8. A payment-processing Lambda function is triggered asynchronously and AWS may retry the event. A retry must never charge a customer twice. What should the developer implement?
- Enable reserved concurrency of 1 so retries never overlap
- Store an idempotency key from the event in DynamoDB with a conditional write (attribute_not_exists) and skip processing if the write fails
- Increase the function timeout so retries are unnecessary
- Move the event source to a standard SQS queue
Answer key
1. B — Lambda allocates CPU in proportion to memory, so more memory makes CPU-bound work finish faster; because billing is per GB-second, a large enough speed-up can lower total cost. A timeout change (A) does not affect speed, and the storage change (D) does not address a CPU bottleneck. (§1.1)
2. C — API keys, usage plans, and built-in request validation are REST API features that HTTP APIs do not offer. A private API (D) addresses network reachability, not these requirements. (§1.2)
3. C — A GSI gives the attribute its own key structure and can be added at any time, but GSIs support eventually consistent reads only. An LSI (B) cannot be added after table creation, and a Scan (A) still reads the whole table. (§1.3) A. The queue is a standard queue; convert it to FIFO to stop duplicates B. The visibility timeout is shorter than processing time; increase it (or extend it during processing) C. Long polling is disabled; enable it to prevent redelivery
4. B — When processing outlives the visibility timeout, the message becomes visible again and is redelivered - duplicates are the expected result on any queue type, not a defect fixed by FIFO (A) or long polling (C). (§1.5)
5. B — Fan-out - SNS topic to one SQS queue per consumer - gives every team every event plus independent retries and DLQs. With a single shared queue (A), each message reaches only one consumer. (§1.5)
6. B — Firehose is a fully managed delivery service that buffers, optionally transforms and converts format (including to Parquet), and writes to S3 - no consumers to build. Data Streams (A) would require writing and operating a consumer. (§1.5)
7. B — The Converse API provides one uniform request shape across models, and ConverseStream delivers incremental output. InvokeModel (A, C) uses model-specific payload formats. (§1.7)
8. B — Idempotency requires the handler itself to detect prior execution: recording the event's unique key atomically and treating a failed condition check as "already processed." Concurrency and timeout settings (A, C) do not prevent sequential retries, and a standard queue (D) also delivers at least once. (§1.8)
Want the full AWS Developer – Associate (DVA-C03) package?
This guide is free to read. Get the downloadable PDF guidebook plus the full DVA-C03 practice exam with 3 months of online access.
Get DVA-C03 Full Access — $10