DVA-C03 development with AWS services
Development with AWS Services is the largest DVA-C03 domain at 30% of scored content (32% on the outgoing DVA-C02). It tests whether a developer can build an application from AWS building blocks and predict how those blocks behave under retries, failures and load. Questions rarely ask for definitions; they describe a symptom or a constraint and ask which service setting or code pattern fits. The AWS exam guide splits it into three tasks: develop code for applications hosted on AWS (1.1), develop code for Lambda (1.2) and use data stores (1.3).
What the domain is about
The guide consolidates four DynamoDB skills into one (skill 1.3.4), and adds AI-assisted code generation and review (1.1.9) and integrating managed AWS AI services into applications (1.1.10). Serialising and deserialising data moved here from the old Task 1.3 into Task 1.1. Lambda performance tuning moved out, to Domain 4. Everything else below is long-standing developer territory.
| Task | Skills AWS lists, in short |
|---|---|
| 1.1 Code for hosted applications | Coupling and decoupling, synchronous versus asynchronous patterns, retry with backoff and graceful degradation, APIs (request and response transformation, validation), SDK use, streaming data, serialisation, event-driven patterns (EventBridge, S3 Event Notifications, SQS, SNS), AI-assisted development tools, managed AI services |
| 1.2 Code for Lambda | Access to private VPC resources, configuration (memory, concurrency, timeout, runtime, handler, layers, extensions), event lifecycles and errors (destinations, dead-letter queues), integration through event source mappings |
| 1.3 Data stores | Data lifecycles (S3 Lifecycle, TTL, retention), choosing a store by access pattern (ElastiCache, DynamoDB, S3, RDS), caching to match the store, DynamoDB configuration (high-cardinality partition keys, read consistency, query and scan, keys and indexes) |
| Area | What to reason about |
|---|---|
| Lambda | Synchronous versus asynchronous invocation, event source mappings, timeouts, concurrency, retries |
| Queues and events | SQS standard and FIFO, visibility timeout, dead-letter queues, SNS fan-out, EventBridge rules |
| DynamoDB | Partition and sort keys, query versus scan, secondary indexes, conditional writes, consistency |
| APIs | API Gateway integrations, request validation, throttling, REST design (see REST API basics) |
| Storage | S3 presigned URLs, multipart upload, event notifications |
| SDK and CLI | Pagination, retries with exponential backoff, credential provider chain |
| Streaming and serialisation | Kinesis and Amazon Data Firehose for streams, marshalling data to and from JSON and DynamoDB attribute formats |
| Lambda in a VPC | Attaching a function to subnets and security groups to reach private resources, and what that means for outbound access |
| Data lifecycle | S3 Lifecycle rules, DynamoDB TTL, retention periods |
| AI in development | AI coding tools (the guide names spec-driven generation, automated review, refactoring suggestions, security scanning) and calling managed AI services such as Amazon Bedrock from application code; review generated code for correctness and security |
How to think about it
Start from the failure mode. Standard SQS queues and Lambda event sources deliver at least once, so handlers must be idempotent, for example by using a conditional write keyed on a business identifier. Asynchronous Lambda invocations are retried by the service, and events that still fail can go to a dead-letter queue or an on-failure destination. With an SQS event source, a batch is retried as a whole unless the function reports which items failed.
For DynamoDB, design the keys from the access patterns. A query needs the partition key; anything else needs an index or becomes a scan, which reads every item and costs accordingly. A global secondary index can be added at any time, can use different keys, and is eventually consistent. A local secondary index shares the table’s partition key, must be created with the table and supports strongly consistent reads. Conditional expressions let a write succeed only if the item is in an expected state, which is the tool for optimistic locking and idempotency. Deeper reading on caching reads sits under DAX basics.
Worked mini-scenario
An order service puts each order on an SQS standard queue. A Lambda function reads batches of ten messages and writes each order to DynamoDB. One malformed message keeps failing, and every few minutes the whole batch is retried, so valid orders are written repeatedly and reappear in reports.
Reasoning: the function throws on the bad message, so Lambda treats the entire batch as failed and the messages return to the queue after the visibility timeout. Two fixes work together. First, enable partial batch responses (reporting batch item failures) so the function returns only the failed message identifiers and Lambda deletes the rest. Second, attach a dead-letter queue to the source queue with a maximum receive count, so the poisonous message is parked after a few attempts. Idempotent writes (a conditional put on the order ID) protect against the remaining at-least-once duplicates. Raising the timeout or the batch size would change neither the redelivery nor the correctness problem.
Easy-to-confuse pairs
| Pair | Distinction |
|---|---|
| SQS versus SNS | SQS holds messages for consumers to pull; SNS pushes one message to many subscribers |
| SNS versus EventBridge | SNS fans out topics; EventBridge routes events by content rules from many sources, including SaaS and AWS services |
| Query versus Scan | Query uses the key condition; Scan reads the whole table or index |
| GSI versus LSI | GSI: any keys, add later, eventual consistency. LSI: same partition key, creation time only, optional strong consistency |
| Visibility timeout versus delay queue | Visibility timeout hides a message after it is received; delay hides it from the moment it is sent |
| Presigned URL versus IAM credentials | A presigned URL grants one time-limited operation on one object without sharing credentials |
| Provisioned versus on-demand capacity | Provisioned suits predictable traffic; on-demand removes capacity planning for spiky or unknown traffic |
An exam-style pitfall
When a scenario says an operation “sometimes happens twice”, the tempting answers tune throughput: more memory, larger batches, longer timeouts. The question is about delivery semantics, and the best answer makes the consumer idempotent or fixes the retry path. The same applies to throttled DynamoDB writes with plenty of total capacity: look at key cardinality before raising capacity.
Own scenario questions
Question 1. A Lambda function processes SQS messages in batches of 10. When one message fails, the whole batch returns to the queue and the nine valid messages are processed again. What is the best fix?
- A. Increase the function timeout to 15 minutes
- B. Increase the batch size to 100
- C. Enable partial batch responses and return the IDs of failed messages
- D. Increase the function memory
Show answer
Answer: C
Reporting batch item failures lets the function return only the failed message IDs, so Lambda deletes the successful messages and only the failed one is retried. A longer timeout, a larger batch or a bigger memory size does not change which messages are retried.
Want more questions like this? Full DVA-C03 practice tests →
Question 2. A DynamoDB table uses OrderId as its partition key. A new screen must list all orders for a given CustomerId, ordered by date, and runs thousands of times per hour. What is the best approach?
- A. Create a global secondary index with CustomerId as partition key and order date as sort key, then query it
- B. Scan the table with a filter expression on CustomerId
- C. Add a local secondary index on CustomerId to the existing table
- D. Increase the table read capacity and keep scanning
Show answer
Answer: A
A global secondary index with CustomerId as partition key and the order date as sort key serves this query efficiently and can be added to an existing table. A scan with a filter reads every item. A local secondary index must share the table partition key and be created with the table, and more read capacity does not remove the scan cost.
Want more questions like this? Full DVA-C03 practice tests →
Question 3. Browser users must upload files of up to 500 MB to a private S3 bucket. The application must not proxy the data and must not ship long-lived credentials to the browser. What should the backend do?
- A. Embed an IAM user access key in the JavaScript
- B. Make the bucket publicly writable
- C. Send the file through API Gateway to a Lambda function that writes it to S3
- D. Return a time-limited presigned URL for the upload
Show answer
Answer: D
A presigned URL generated by the backend lets the browser upload one object directly to S3 for a limited time without holding credentials. Embedded access keys are long-lived secrets, a public-write bucket is unsafe, and proxying through an API and function adds payload limits and cost.
Want more questions like this? Full DVA-C03 practice tests →
Where to go next
Domain 2 builds on the same services with identity and encryption: security explained. For how the 30% fits the rest of the exam, see the study plan and the exam format.