AWS · DVA-C02
DVA-C02 practice questions with answers
15 free practice questions for the AWS Certified Developer – Associate (DVA-C02) exam, spread across the exam's domains. Try each one, then open the answer to see why every option is right or wrong.
Question 1 · Development with AWS Services
A developer calls UpdateItem with the update expression SET Status = :s. The call fails with a ValidationException saying the expression uses a reserved keyword. Which change lets the update succeed while still writing to the existing Status attribute?
- AMap #st to Status in ExpressionAttributeValues and use SET #st = :s
- BWrite the attribute as lowercase status, since reserved-word checks are case-sensitive
- CMap #st to Status in ExpressionAttributeNames and use SET #st = :s
- DMap :st to the string Status in ExpressionAttributeValues and use SET :st = :s
Show answer and explanation
Answer: C) Map #st to Status in ExpressionAttributeNames and use SET #st = :s
When an attribute name is a DynamoDB reserved word such as STATUS, define an expression attribute name (for example #st) in ExpressionAttributeNames and use it in the expression. Expression attribute values (starting with :) stand in only for data values.
- AExpressionAttributeValues holds placeholders for values, and those must start with a colon. Placeholders for attribute names starting with # belong in ExpressionAttributeNames.
- BThe DynamoDB reserved word list isn't case-sensitive, so 'status' conflicts just as 'Status' does. Writing to a different-cased name would also target a different attribute.
- CAn expression attribute name is a placeholder starting with #. DynamoDB swaps in the real attribute name, which avoids the reserved-word conflict. The same mechanism is required for names that contain dots or hyphens, start with a number, or contain spaces.
- DExpression attribute values stand in for data values being compared or assigned. They can't be used as the attribute name on the left side of a SET action.
Question 2 · Development with AWS Services
An application runs active-active in two AWS Regions. Each Region reads and writes its local replica of a DynamoDB global table that uses the default multi-Region eventual consistency (MREC) mode. Users in both Regions update the same item at nearly the same moment. How does DynamoDB handle the conflicting writes?
- ABoth writes succeed locally, and every replica eventually converges on the write with the latest internal timestamp for that item
- BThe second write fails with a ReplicatedWriteConflictException, and the application must retry it after the first write replicates
- CDynamoDB keeps both conflicting versions as separate item versions and returns both on reads until the application merges them
- DReplication for the affected item is paused until an administrator selects the winning version in the DynamoDB console
Show answer and explanation
Answer: A) Both writes succeed locally, and every replica eventually converges on the write with the latest internal timestamp for that item
In an active-active design, the team has to plan for cross-Region write conflicts. DynamoDB global tables in MREC mode resolve them automatically per item with last writer wins, based on the latest internal timestamp, while MRSC mode rejects conflicting writes with ReplicatedWriteConflictException.
- AIn MREC mode, changes replicate asynchronously. When the same item is modified in multiple Regions at the same time, DynamoDB uses a per-item "last writer wins" rule based on the latest internal timestamp, and all replicas eventually converge on that version.
- BReplicatedWriteConflictException is returned by global tables in multi-Region strong consistency (MRSC) mode. The table in this scenario uses MREC, which resolves conflicts with last writer wins.
- CDynamoDB does not keep multiple conflicting versions of an item for the application to merge. Each item converges to a single version on every replica.
- DConflict resolution is automatic. MREC global tables need no manual step to pick a winner, and replication of the item is not paused.
Question 3 · Development with AWS Services
A Node.js Lambda function calls only Amazon DynamoDB, but its code imports the entire AWS SDK. Its .zip deployment package also includes a large charting library that the code never uses. The function's Init Duration has grown noticeably. Which change most directly cuts the initialization time without adding cost?
- AImport only the DynamoDB client and remove the unused charting library from the deployment package
- BMove the full AWS SDK and the charting library into a Lambda layer attached to the function
- CIncrease the function's timeout setting so the initialization phase has more time to complete
- DConfigure reserved concurrency on the function so that its execution environments stay warm
Show answer and explanation
Answer: A) Import only the DynamoDB client and remove the unused charting library from the deployment package
Cold-start init time grows with the code Lambda has to load, including layers. Removing unused dependencies and importing only the clients you need reduces init time directly. Layers, longer timeouts and reserved concurrency don't.
- ACorrect. AWS says init latency depends on the size of the function package (imported libraries, dependencies and layers). It recommends importing only the libraries a function needs, such as a single service client instead of the entire SDK.
- BIncorrect. A layer makes the deployment package smaller, but Lambda still extracts the layer into the execution environment. AWS lists layers as a factor in initialization latency, so the same code still has to load.
- CIncorrect. The function timeout limits how long an invocation may run. It doesn't make initialization faster, so cold starts take just as long.
- DIncorrect. Reserved concurrency reserves and caps how many instances can run at once. It doesn't pre-initialize environments. Provisioned concurrency does that, but it costs extra.
Question 4 · Development with AWS Services
A developer's application calls SendMessage once to place a single 256 KB message on an Amazon SQS standard queue. How many billable requests does SQS count for this call?
- A1 request, because SQS bills per API call regardless of payload size
- B4 requests, because each 64 KB chunk of the payload is billed as one request
- C2 requests, because each 128 KB chunk of the payload is billed as one request
- D16 requests, because every message is billed at the 1 MiB maximum payload size
Show answer and explanation
Answer: B) 4 requests, because each 64 KB chunk of the payload is billed as one request
SQS bills each 64 KB chunk of a request payload as one request. A single 256 KB SendMessage call therefore counts as 4 billable requests. The current maximum message size is 1 MiB, which is billed as 16 requests.
- APayload size does affect billing. SQS bills each 64 KB chunk of a payload as one request, so a single API call can count as several requests.
- BAccording to the SQS pricing page, each 64 KB chunk of a payload is billed as 1 request. A 256 KB payload contains four 64 KB chunks, so it counts as 4 requests, even though the application made only one SendMessage call.
- CThe billing increment is 64 KB, not 128 KB. Using 128 KB would undercount this call by half.
- D16 requests is what a full 1 MiB payload costs (16 × 64 KB). SQS bills the actual payload in 64 KB chunks, not the maximum allowed size.
Question 5 · Development with AWS Services
A CloudFront distribution serves static assets from an S3 bucket in us-east-1. A copy of the data is kept in a second bucket in us-west-2. When the primary bucket returns 5xx errors or cannot be reached, the team wants CloudFront to automatically retrieve the objects from the second bucket. What should the developer configure?
- ACreate an origin group with both buckets, set the us-east-1 bucket as primary, select failover status codes, and use the origin group in the cache behavior.
- BTurn on CloudFront Origin Shield in us-west-2 so that the regional caching layer gets objects from the second bucket when the primary returns errors.
- CAdd a second cache behavior with a path pattern that points to the us-west-2 bucket, so that CloudFront uses it when the default behavior returns errors.
- DSet up S3 Cross-Region Replication to the us-west-2 bucket, and CloudFront detects the replica and sends requests to it when the source bucket fails.
Show answer and explanation
Answer: A) Create an origin group with both buckets, set the us-east-1 bucket as primary, select failover status codes, and use the origin group in the cache behavior.
CloudFront origin failover is configured with an origin group that has a primary and a secondary origin and selected failover status codes. The origin group is then used as the cache behavior's origin. Replication or caching features alone do not reroute requests.
- ACorrect. An origin group has a primary and a secondary origin. When the primary returns a status code configured for failover, or CloudFront cannot connect to it (with 503 set as a failover code), CloudFront sends the request to the secondary origin. Failover applies to GET, HEAD, and OPTIONS requests.
- BIncorrect. Origin Shield is an extra caching layer that cuts down the number of requests reaching an origin. It does not switch requests to a different origin when the primary fails.
- CIncorrect. Cache behaviors choose an origin by matching the request path, not by checking origin health. Requests that match the default behavior keep going to the primary bucket even when it returns errors.
- DIncorrect. Replication keeps the second bucket's data in sync, but CloudFront does not know about replica buckets. The second bucket must be added as an origin and placed in an origin group as the secondary before CloudFront can fail over to it.
Question 6 · Security
A shared S3 bucket holds data for many teams. A partner's IAM role in another AWS account needs read-only access to objects under the partners/acme/ prefix only. The bucket policy is already long, and the team wants to manage each consumer's permissions separately. Which approach fits this requirement?
- ACreate an S3 access point for the partner with a policy that allows s3:GetObject on the partners/acme/ prefix
- BEnable S3 Requester Pays on the bucket so the partner's account is billed for and authorized to make its requests
- CSet S3 Object Ownership to bucket owner enforced so the partner's role is granted ownership of the prefix
- DApply S3 Object Lock in governance mode to the partners/acme/ prefix to restrict reads to the partner's role
Show answer and explanation
Answer: A) Create an S3 access point for the partner with a policy that allows s3:GetObject on the partners/acme/ prefix
S3 access points give each consumer its own named endpoint and policy, which can be limited to a prefix. The bucket policy must also allow the access, usually by delegating access control to access points.
- AEach access point has its own policy, so each consumer's permissions can be managed separately and limited to a prefix. The underlying bucket must also allow the request. The recommended way is a bucket policy that delegates access control to access points, using the s3:DataAccessPointAccount condition.
- BRequester Pays only moves request and data transfer charges to the requester. It does not grant permissions or limit access to a prefix.
- CBucket owner enforced disables ACLs and makes the bucket owner the owner of every object. It does not give another account ownership of a prefix or read access to it.
- DObject Lock prevents object versions from being deleted or overwritten for a retention period. It does not control who can read objects.
Question 7 · Security
In Secrets Manager, what do the AWSCURRENT and AWSPREVIOUS staging labels represent during a secret rotation?
- AAWSCURRENT marks the version an application should currently retrieve and use; AWSPREVIOUS marks the prior version, kept briefly to support rollback or in-flight processes still using the old credential during rotation
- BThey have no functional meaning and are purely decorative labels
- CAWSPREVIOUS always represents a newer version than AWSCURRENT
- DThese labels only apply to secrets that are never rotated
Show answer and explanation
Answer: A) AWSCURRENT marks the version an application should currently retrieve and use; AWSPREVIOUS marks the prior version, kept briefly to support rollback or in-flight processes still using the old credential during rotation
- ADuring rotation, Secrets Manager creates a new secret version and moves the AWSCURRENT label to it once rotation completes successfully, while the previous version (still valid briefly, depending on the rotation strategy) keeps the AWSPREVIOUS label — giving a short grace period rather than an instantaneous hard cutover that could break in-flight operations.
- BThese labels have real functional meaning — applications retrieving "the current secret" specifically fetch the version labeled AWSCURRENT, and Secrets Manager's own rotation logic relies on them.
- CThis reverses their actual meaning — AWSCURRENT is the active, latest version; AWSPREVIOUS is the older one being phased out.
- DThese staging labels are specifically meaningful in the context of rotation — a secret that's never rotated typically only ever has the single AWSCURRENT version with no AWSPREVIOUS to speak of.
Question 8 · Security
A mobile app authenticates against an Amazon Cognito user pool through an app client created with default settings. During a security review, the team asks what happens to a user's refresh token after the app uses it to get new tokens, and how to change that behavior. Which statement is accurate?
- AThe app receives new ID and access tokens and the original refresh token stays valid; enabling refresh token rotation on the app client makes each refresh return a new refresh token.
- BThe app receives new ID, access, and refresh tokens and the original is revoked, because rotation is a fixed user pool behavior that the app client cannot change.
- CThe app receives new ID and access tokens only; to rotate, the app must call InitiateAuth with the REFRESH_TOKEN_AUTH flow, which issues a new refresh token on each call.
- DThe app receives new ID and access tokens, and the refresh token's validity restarts for its full configured period from the time of each refresh.
Show answer and explanation
Answer: A) The app receives new ID and access tokens and the original refresh token stays valid; enabling refresh token rotation on the app client makes each refresh return a new refresh token.
Cognito app clients don't rotate refresh tokens by default, so the original refresh token stays valid after each refresh. Turning on refresh token rotation, which AWS recommends as a security best practice, makes each refresh return a new refresh token and invalidate the old one within the original validity window.
- ARefresh token rotation is an optional app client setting. When it is disabled, token-refresh requests return only new access and ID tokens and the original refresh token remains valid. When it is enabled, each refresh also returns a new refresh token and invalidates the original one, with an optional grace period of up to 60 seconds.
- BRotation isn't fixed. It is configured on each app client in the console or with RefreshTokenRotation in CreateUserPoolClient/UpdateUserPoolClient. Without it, refreshes don't issue a new refresh token.
- CREFRESH_TOKEN_AUTH isn't compatible with refresh token rotation. App clients that use rotation must disable that flow and refresh with GetTokensFromRefreshToken or the token endpoint.
- DRefresh tokens don't have a sliding expiration. Even with rotation enabled, each new refresh token is valid only for the time left on the original RefreshTokenValidity window, so the user must sign in again when that window ends.
Question 9 · Security
A developer creates a CloudTrail trail with its default event settings. During an audit, the trail's log files contain CreateBucket and PutBucketPolicy calls for an S3 bucket, but there are no records of which principals called GetObject on objects in that bucket. What explains this, and how can the missing activity be captured?
- AGetObject is a data event, and trails don't log data events by default; add an event selector for S3 data events on the trail
- BGetObject is a read-only management event, and by default a trail logs only write management events; enable Read events on the trail
- CObject-level S3 calls go only to CloudTrail Event history, not to trails; query Event history for GetObject records from the last 90 days
- DGetObject is recorded as a CloudTrail Insights event, which is disabled by default; enable Insights on the trail to log object reads
Show answer and explanation
Answer: A) GetObject is a data event, and trails don't log data events by default; add an event selector for S3 data events on the trail
CloudTrail management events are control plane operations such as CreateBucket and are logged by trails by default. Data events are high-volume data plane operations such as S3 GetObject or Lambda Invoke, are not logged by default, and must be enabled with event selectors at additional cost.
- ACorrect. GetObject is an object-level (data plane) operation, so CloudTrail records it as a data event. By default, trails log management events but not data events. You must add basic or advanced event selectors to log them, and additional charges apply.
- BIncorrect. By default, a trail logs all management events, both Read and Write. Also, GetObject isn't a management event. It is an S3 object-level data event.
- CIncorrect. CloudTrail Event history supports only management events, so it doesn't contain S3 object-level data events such as GetObject. Those events are captured only when a trail or event data store is configured to log data events.
- DIncorrect. Insights events flag unusual API call rates or error rates, based on management event activity. They don't record individual GetObject calls. Logging object-level reads requires data event logging.
Question 10 · Deployment
A release pipeline in AWS CodePipeline has a manual approval action before the production deploy stage. Right now, an unanswered approval request stays pending for days before it fails. The team wants an unanswered request for this one action to fail after 2 hours, without changing any other pipelines in the account. What should a developer do?
- ASet timeoutInMinutes to 120 in the manual approval action's declaration in the pipeline structure
- BSet the build timeout to 120 minutes on the CodeBuild project used in the production deploy stage
- CChange the delivery policy of the approval's Amazon SNS topic so that retries stop after 120 minutes
- DSet the --cli-read-timeout option to 7200 seconds in the AWS CLI profile that approvers use
Show answer and explanation
Answer: A) Set timeoutInMinutes to 120 in the manual approval action's declaration in the pipeline structure
In CodePipeline, you can set a per-action timeout (timeoutInMinutes) only on manual approval actions, where it overrides the 7-day default. Timeouts for other action types, such as the CodeBuild build action, are fixed service values, and timeouts configured in other services don't change how long an approval waits.
- ACorrect. The ActionDeclaration timeoutInMinutes attribute overrides the default timeout (7 days at the account level) for a single action. It works only for the manual approval action type and accepts values from 5 to 86400 minutes.
- BIncorrect. A CodeBuild project timeout only limits how long that project's builds run. It has no effect on how long a separate approval action waits for a response.
- CIncorrect. The SNS delivery policy controls retries for notification delivery. It doesn't change how long CodePipeline keeps the approval action waiting before marking it failed.
- DIncorrect. That option only controls how long the local CLI waits for a socket read. It doesn't affect any timeout inside the pipeline.
Question 11 · Deployment
A developer deploys an application to an Elastic Beanstalk environment with several EC2 instances. Two requirements must be defined in the application source bundle: every instance must have a specific yum package installed, and a database migration script must run on only one instance during each deployment. Which approach meets both requirements?
- AAdd a .config file in the .ebextensions folder that uses the packages key and a container_commands entry with leader_only set to true
- BAdd a Buildfile at the root of the source bundle that runs the yum install command and then the migration script
- CAdd a Procfile at the root of the source bundle that defines one process for the package install and one for the migration
- DAdd the package name and migration command to the .elasticbeanstalk/config.yml file used by the EB CLI
Show answer and explanation
Answer: A) Add a .config file in the .ebextensions folder that uses the packages key and a container_commands entry with leader_only set to true
.ebextensions configuration files can install OS packages with the packages key and run commands on a single instance with container_commands leader_only. Buildfile and Procfile cannot limit execution to one instance, and config.yml only holds local EB CLI settings.
- ACorrect. In .ebextensions configuration files, the packages key installs packages (yum is supported) on every instance. A container_commands entry with leader_only: true runs on a single instance that Elastic Beanstalk chooses during deployments.
- BIncorrect. A Buildfile runs short build or configuration commands, but it runs on every instance. It cannot limit the migration to a single instance, and it has no declarative way to specify packages.
- CIncorrect. A Procfile defines long-running application processes. Elastic Beanstalk expects them to keep running and restarts any that exit, so it is not suitable for one-time install or migration steps.
- DIncorrect. The .elasticbeanstalk/config.yml file stores local EB CLI settings, such as the default application, environment and Region. It does not install packages or run commands on instances.
Question 12 · Deployment
A developer has a new version of an Amazon API Gateway REST API ready for the prod stage. The team wants a small, random share of prod requests to reach the new version and to compare its error metrics with the current version. Depending on the results, they will either move all traffic to the new version or discard it. They want to use API Gateway's own stage features, not Lambda aliases with AWS CodeDeploy. Which approach meets these requirements?
- AAdd canary settings to the prod stage with a traffic percentage for the new deployment, then promote or turn off the canary
- BDeploy the new version to a second stage and use a prod stage variable to forward a share of requests to that stage
- CAttach a usage plan to the new deployment and slowly raise its throttling limits until it handles all of the requests
- DImport the new version as a separate REST API and use a Route 53 weighted record to split traffic between both APIs
Show answer and explanation
Answer: A) Add canary settings to the prod stage with a traffic percentage for the new deployment, then promote or turn off the canary
An API Gateway canary release adds canary settings to a stage so that a set percentage of the stage's traffic goes to a new deployment. After checking the canary's own logs and metrics, you promote it or turn it off.
- ACorrect. A canary release adds canarySettings (a deployment ID and a traffic percentage from 0.0 to 100.0) to an existing stage. The canary has its own CloudWatch log group. You can then promote the canary to be the production release or turn it off to discard the changes.
- BIncorrect. A stage variable holds one value for every request to the stage, so it cannot split traffic by percentage. To split traffic within a single stage, you use canary settings.
- CIncorrect. A usage plan sets throttling limits and quotas for API keys. It does not route traffic between deployments of a stage.
- DIncorrect. A Route 53 weighted record can split traffic between two separate APIs, but that is DNS routing outside API Gateway, not a stage feature. A canary release does the split within the same stage and gives the canary its own logs and metrics.
Question 13 · Troubleshooting and Optimization
A developer's code calls the Amazon SNS Publish API with the PhoneNumber parameter to send an SMS message directly to a customer. The call fails with an HTTP 400 InvalidParameter error that refers to the phone number. What is the most likely cause?
- AThe number was passed in a local format such as 555-0100 instead of E.164 format
- BThe IAM role used by the application does not allow the sns:Publish action
- CThe SMS message body is longer than the 140-character single-message limit
- DThe Publish request did not include a Subject parameter for the SMS message
Show answer and explanation
Answer: A) The number was passed in a local format such as 555-0100 instead of E.164 format
When you publish an SMS directly to a phone number, SNS requires the number in E.164 format (+, country code, number). A badly formatted number fails parameter validation with InvalidParameter.
- ACorrect. The Publish API requires the PhoneNumber value in E.164 format: a plus sign, the country code and the subscriber number, with no dashes or spaces (for example, +14155550100). A locally formatted number breaks this rule, so SNS returns InvalidParameter (HTTP 400).
- BIncorrect. A missing permission returns an AuthorizationError with HTTP 403. It does not return a 400 InvalidParameter error about the phone number.
- CIncorrect. When an SMS message is longer than the per-message limit, SNS splits it into several messages at word boundaries, up to 1,600 characters per Publish call. Being over 140 characters does not cause an error about the phone number.
- DIncorrect. Subject is optional and is used as the subject line for email endpoints. Leaving it out of an SMS publish does not cause a validation error.
Question 14 · Troubleshooting and Optimization
A Lambda function reads from a Kinesis data stream through an event source mapping. CloudWatch Logs shows that many invocations time out before they finish processing the records they receive. The team can't raise the function timeout any further. Which event source mapping change most directly reduces the work every invocation, including first attempts, must complete?
- ALower the BatchSize value so that Lambda delivers fewer records to the function in each invocation
- BRaise MaximumBatchingWindowInSeconds so that Lambda buffers records longer before invoking the function
- CRaise ParallelizationFactor so that Lambda processes several batches from each shard at the same time
- DTurn on BisectBatchOnFunctionError so that Lambda splits a batch into halves after an invocation fails
Show answer and explanation
Answer: A) Lower the BatchSize value so that Lambda delivers fewer records to the function in each invocation
BatchSize sets how many records Lambda sends in each invocation, so lowering it directly reduces the work per invocation. A batching window enlarges batches, ParallelizationFactor adds concurrency, and bisecting only reacts after a failure.
- ACorrect. BatchSize sets the maximum number of records Lambda reads from a shard and sends in one invocation (default 100, maximum 10,000 for Kinesis). Lowering it reduces the work in every invocation, so each one is more likely to finish within the timeout.
- BIncorrect. A batching window makes Lambda keep gathering records until the batch is full, the window expires, or the 6 MB payload limit is reached. This tends to make batches larger, which adds to the work per invocation.
- CIncorrect. ParallelizationFactor (1 to 10) increases the number of concurrent batches per shard and so increases throughput. Each batch is still up to BatchSize records, so the work in a single invocation doesn't shrink.
- DIncorrect. Bisecting happens only after an invocation returns an error, and the smaller halves are then retried. First attempts still receive full-size batches and can still time out, so this doesn't reduce the work every invocation must do.
Question 15 · Troubleshooting and Optimization
A Python Lambda function has high duration and CPU usage in production. A developer wants to find which methods and lines of code use the most CPU time, ideally shown as a visualization of the call stack. The developer doesn't want to add custom timing code throughout the codebase. Which AWS service should the developer use?
- AAmazon CodeGuru Profiler, which samples the running function's call stacks and shows its most CPU-intensive code
- BAWS X-Ray active tracing, which records each invocation's segments and subsegments for downstream service calls
- CAmazon CloudWatch Lambda Insights, which collects CPU time, memory and network metrics for each invocation
- DAmazon CloudWatch Logs Insights, which runs queries against the function's REPORT log lines to find slow requests
Show answer and explanation
Answer: A) Amazon CodeGuru Profiler, which samples the running function's call stacks and shows its most CPU-intensive code
CodeGuru Profiler samples a running application and shows which code paths use the most CPU, with no manual instrumentation. X-Ray, Lambda Insights and Logs Insights work at the request or function level and need custom code to give line-level timing.
- ACorrect. CodeGuru Profiler collects runtime performance data from live applications, including Lambda functions written in Python or JVM languages. Its visualizations show which code is running on the CPU and how much time it takes, which helps find the most expensive lines of code without manual timing code.
- BIncorrect. X-Ray shows request-level latency across services and downstream calls. To time specific functions or lines of code, the developer must add custom subsegments to the code, which is the manual instrumentation the team wants to avoid.
- CIncorrect. Lambda Insights collects system-level metrics such as CPU time, memory, disk and network for the whole function. It can confirm high CPU usage but can't show which methods or lines of code cause it.
- DIncorrect. Logs Insights can query duration and memory values from Lambda REPORT log lines. It can't show code-level CPU usage unless the developer adds custom timing logs throughout the code.
Ready for a full DVA-C02 practice exam?
These are a sample from the CertRidge question bank. Full practice exams match the real exam's length, time limit and domain weights, with every answer explained.
Original questions written from the official exam guide. Not affiliated with AWS; never copied from the real exam.